blob: 96e97003b720f82c166b1aab741f954f2bf4d6eb [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
9721sub selectType($$)
9722{
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 Ponomarenko62ddcfa2012-05-23 13:13:15 +04009736 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9737 {
9738 if(not isBuiltIn($THeader))
9739 {
9740 if($TypeInfo{$LibVersion}{$Tid}{"Type"}=~/Class|Struct|Union|Enum|Typedef/)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009741 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009742 if(not isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"}))
9743 {
9744 if(is_target_header($THeader, $LibVersion))
9745 { # from target headers
9746 if(not selfTypedef($Tid, $LibVersion)) {
9747 return 1;
9748 }
9749 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009750 }
9751 }
9752 }
9753 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009754 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009755}
9756
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009757sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009758{ # remove unused data types from the ABI dump
9759 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009760
9761 my %UsedType = ();
9762
9763 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009764 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009765 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009766 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009767 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009768 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009769 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009770 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009771 next;
9772 }
9773
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009774 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009775 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009776 if(selectType($Tid, $LibVersion))
9777 {
9778 my %Tree = ();
9779 register_TypeUsage($Tid, \%Tree, $LibVersion);
9780
9781 my $Tmpl = 0;
9782 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9783 {
9784 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9785 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9786 {
9787 $Tmpl = 1;
9788 last;
9789 }
9790 }
9791 if(not $Tmpl)
9792 {
9793 foreach (keys(%Tree)) {
9794 $UsedType{$_} = 1;
9795 }
9796 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009797 }
9798 }
9799 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009800
9801 my %Delete = ();
9802
9803 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009804 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009805 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009806 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009807 next;
9808 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009809
9810 if($Kind eq "Extra")
9811 {
9812 my %Tree = ();
9813 register_TypeUsage($Tid, \%Tree, $LibVersion);
9814
9815 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9816 {
9817 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9818 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9819 {
9820 $Delete{$Tid} = 1;
9821 last;
9822 }
9823 }
9824 }
9825 else
9826 {
9827 # remove type
9828 delete($TypeInfo{$LibVersion}{$Tid});
9829 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009830 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009831
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009832 if($Kind eq "Extra")
9833 { # remove duplicates
9834 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9835 {
9836 if($UsedType{$Tid})
9837 { # All & Extended
9838 next;
9839 }
9840
9841 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9842
9843 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9844 delete($TypeInfo{$LibVersion}{$Tid});
9845 }
9846 }
9847 }
9848
9849 foreach my $Tid (keys(%Delete))
9850 {
9851 delete($TypeInfo{$LibVersion}{$Tid});
9852 }
9853}
9854
9855sub check_Completeness($$)
9856{
9857 my ($Info, $LibVersion) = @_;
9858
9859 # data types
9860 if(defined $Info->{"Memb"})
9861 {
9862 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9863 {
9864 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9865 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9866 }
9867 }
9868 }
9869 if(defined $Info->{"Base"})
9870 {
9871 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9872 check_TypeInfo($Bid, $LibVersion);
9873 }
9874 }
9875 if(defined $Info->{"BaseType"}) {
9876 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9877 }
9878 if(defined $Info->{"TParam"})
9879 {
9880 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9881 {
9882 my $TName = $Info->{"TParam"}{$Pos}{"name"};
9883 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
9884 next;
9885 }
9886 if($TName eq "_BoolType") {
9887 next;
9888 }
9889 if($TName=~/\Asizeof\(/) {
9890 next;
9891 }
9892 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
9893 check_TypeInfo($Tid, $LibVersion);
9894 }
9895 else
9896 {
9897 if(defined $Debug) {
9898 printMsg("WARNING", "missed type $TName");
9899 }
9900 }
9901 }
9902 }
9903
9904 # symbols
9905 if(defined $Info->{"Param"})
9906 {
9907 foreach my $Pos (keys(%{$Info->{"Param"}}))
9908 {
9909 if(defined $Info->{"Param"}{$Pos}{"type"}) {
9910 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
9911 }
9912 }
9913 }
9914 if(defined $Info->{"Return"}) {
9915 check_TypeInfo($Info->{"Return"}, $LibVersion);
9916 }
9917 if(defined $Info->{"Class"}) {
9918 check_TypeInfo($Info->{"Class"}, $LibVersion);
9919 }
9920}
9921
9922sub check_TypeInfo($$)
9923{
9924 my ($Tid, $LibVersion) = @_;
9925
9926 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
9927 return;
9928 }
9929 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
9930
9931 if(defined $TypeInfo{$LibVersion}{$Tid})
9932 {
9933 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
9934 printMsg("ERROR", "missed type name ($Tid)");
9935 }
9936 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
9937 }
9938 else {
9939 printMsg("ERROR", "missed type id $Tid");
9940 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009941}
9942
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009943sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009944{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009945 my ($TypeId, $LibVersion) = @_;
9946 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009947 if($Type{"Type"} eq "Typedef")
9948 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009949 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009950 if($Base{"Type"}=~/Class|Struct/)
9951 {
9952 if($Type{"Name"} eq $Base{"Name"}) {
9953 return 1;
9954 }
9955 elsif($Type{"Name"}=~/::(\w+)\Z/)
9956 {
9957 if($Type{"Name"} eq $Base{"Name"}."::".$1)
9958 { # QPointer<QWidget>::QPointer
9959 return 1;
9960 }
9961 }
9962 }
9963 }
9964 return 0;
9965}
9966
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009967sub addExtension($)
9968{
9969 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009970 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009971 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009972 if(selectType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009973 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009974 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9975 $TName=~s/\A(struct|union|class|enum) //;
9976 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009977
9978 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
9979 "Header" => "extended.h",
9980 "ShortName" => $Symbol,
9981 "MnglName" => $Symbol,
9982 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
9983 );
9984
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009985 $ExtendedSymbols{$Symbol} = 1;
9986 $CheckedSymbols{"Binary"}{$Symbol} = 1;
9987 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009988 }
9989 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009990 $ExtendedSymbols{"external_func_0"} = 1;
9991 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
9992 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009993}
9994
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009995sub findMethod($$$)
9996{
9997 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009998 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009999 {
10000 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10001 return $VirtMethodInClass;
10002 }
10003 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10004 return $VirtMethodInBaseClasses;
10005 }
10006 }
10007 return "";
10008}
10009
10010sub findMethod_Class($$$)
10011{
10012 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010013 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010014 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10015 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10016 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10017 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10018 { # search for interface with the same parameters suffix (overridden)
10019 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10020 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010021 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10022 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010023 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10024 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010025 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10026 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10027 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10028 return $Candidate;
10029 }
10030 }
10031 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010032 else
10033 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010034 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10035 return $Candidate;
10036 }
10037 }
10038 }
10039 }
10040 return "";
10041}
10042
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010043sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010044{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010045 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010046 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010047 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010048 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10049 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010050 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010051 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010052 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010053 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10054 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010055 { # pure virtual D2-destructors are marked as "virt" in the dump
10056 # virtual D2-destructors are NOT marked as "virt" in the dump
10057 # both destructors are not presented in the v-table
10058 next;
10059 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010060 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010061 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10062 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010063 }
10064}
10065
10066sub registerOverriding($)
10067{
10068 my $LibVersion = $_[0];
10069 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010070 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010071 foreach my $ClassName (@Classes)
10072 {
10073 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10074 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010075 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10076 { # pure virtuals
10077 next;
10078 }
10079 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10080 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010081 {
10082 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10083 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10084 { # both overridden virtual methods
10085 # and implemented pure virtual methods
10086 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10087 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10088 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10089 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010090 }
10091 }
10092 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10093 delete($VirtualTable{$LibVersion}{$ClassName});
10094 }
10095 }
10096}
10097
10098sub setVirtFuncPositions($)
10099{
10100 my $LibVersion = $_[0];
10101 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10102 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010103 my ($Num, $Rel) = (1, 0);
10104
10105 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010106 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010107 if($UsedDump{$LibVersion}{"DWARF"}) {
10108 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10109 }
10110 else {
10111 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10112 }
10113 foreach my $VirtFunc (@Funcs)
10114 {
10115 if($UsedDump{$LibVersion}{"DWARF"}) {
10116 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10117 }
10118 else {
10119 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10120 }
10121
10122 # set relative positions
10123 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10124 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10125 { # relative position excluding added and removed virtual functions
10126 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10127 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10128 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10129 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010130 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010131 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010132 }
10133 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010134 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010135 {
10136 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010137 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010138 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010139 }
10140 }
10141}
10142
10143sub get_sub_classes($$$)
10144{
10145 my ($ClassId, $LibVersion, $Recursive) = @_;
10146 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10147 my @Subs = ();
10148 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10149 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010150 if($Recursive)
10151 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010152 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10153 push(@Subs, $SubSubId);
10154 }
10155 }
10156 push(@Subs, $SubId);
10157 }
10158 return @Subs;
10159}
10160
10161sub get_base_classes($$$)
10162{
10163 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010164 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010165 return () if(not defined $ClassType{"Base"});
10166 my @Bases = ();
10167 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10168 keys(%{$ClassType{"Base"}}))
10169 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010170 if($Recursive)
10171 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010172 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10173 push(@Bases, $SubBaseId);
10174 }
10175 }
10176 push(@Bases, $BaseId);
10177 }
10178 return @Bases;
10179}
10180
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010181sub getVTable_Model($$)
10182{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010183 my ($ClassId, $LibVersion) = @_;
10184 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10185 my @Elements = ();
10186 foreach my $BaseId (@Bases, $ClassId)
10187 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010188 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010189 {
10190 if(defined $VirtualTable{$LibVersion}{$BName})
10191 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010192 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10193 if($UsedDump{$LibVersion}{"DWARF"}) {
10194 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10195 }
10196 else {
10197 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10198 }
10199 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010200 push(@Elements, $VFunc);
10201 }
10202 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010203 }
10204 }
10205 return @Elements;
10206}
10207
10208sub getVShift($$)
10209{
10210 my ($ClassId, $LibVersion) = @_;
10211 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10212 my $VShift = 0;
10213 foreach my $BaseId (@Bases)
10214 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010215 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010216 {
10217 if(defined $VirtualTable{$LibVersion}{$BName}) {
10218 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10219 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010220 }
10221 }
10222 return $VShift;
10223}
10224
10225sub getShift($$)
10226{
10227 my ($ClassId, $LibVersion) = @_;
10228 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10229 my $Shift = 0;
10230 foreach my $BaseId (@Bases)
10231 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010232 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010233 {
10234 if($Size!=1)
10235 { # not empty base class
10236 $Shift+=$Size;
10237 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010238 }
10239 }
10240 return $Shift;
10241}
10242
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010243sub getVTable_Size($$)
10244{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010245 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010246 my $Size = 0;
10247 # three approaches
10248 if(not $Size)
10249 { # real size
10250 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10251 $Size = keys(%VTable);
10252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010253 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010254 if(not $Size)
10255 { # shared library symbol size
10256 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10257 $Size /= $WORD_SIZE{$LibVersion};
10258 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010259 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010260 if(not $Size)
10261 { # model size
10262 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10263 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10264 }
10265 }
10266 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010267}
10268
10269sub isCopyingClass($$)
10270{
10271 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010272 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010273}
10274
10275sub isLeafClass($$)
10276{
10277 my ($ClassId, $LibVersion) = @_;
10278 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10279}
10280
10281sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010282{ # check structured type for public fields
10283 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010284}
10285
10286sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010287{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010288 my ($TypePtr, $Skip, $Start, $End) = @_;
10289 return 0 if(not $TypePtr);
10290 if($End==-1) {
10291 $End = keys(%{$TypePtr->{"Memb"}})-1;
10292 }
10293 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}}))
10294 {
10295 if($Skip and $Skip->{$MemPos})
10296 { # skip removed/added fields
10297 next;
10298 }
10299 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10300 {
10301 if(isPublic($TypePtr, $MemPos)) {
10302 return ($MemPos+1);
10303 }
10304 }
10305 }
10306 return 0;
10307}
10308
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010309sub isReserved($)
10310{ # reserved fields == private
10311 my $MName = $_[0];
10312 if($MName=~/reserved|padding|f_spare/i) {
10313 return 1;
10314 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010315 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010316 return 1;
10317 }
10318 if($MName=~/(pad\d+)/i) {
10319 return 1;
10320 }
10321 return 0;
10322}
10323
10324sub isPublic($$)
10325{
10326 my ($TypePtr, $FieldPos) = @_;
10327 return 0 if(not $TypePtr);
10328 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10329 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10330 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10331 { # by name in C language
10332 # FIXME: add other methods to detect private members
10333 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10334 if($MName=~/priv|abidata|parent_object/i)
10335 { # C-styled private data
10336 return 0;
10337 }
10338 if(lc($MName) eq "abi")
10339 { # ABI information/reserved field
10340 return 0;
10341 }
10342 if(isReserved($MName))
10343 { # reserved fields
10344 return 0;
10345 }
10346 return 1;
10347 }
10348 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10349 { # by access in C++ language
10350 return 1;
10351 }
10352 return 0;
10353}
10354
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010355sub getVTable_Real($$)
10356{
10357 my ($ClassName, $LibVersion) = @_;
10358 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10359 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010360 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010361 if(defined $Type{"VTable"}) {
10362 return %{$Type{"VTable"}};
10363 }
10364 }
10365 return ();
10366}
10367
10368sub cmpVTables($)
10369{
10370 my $ClassName = $_[0];
10371 my $Res = cmpVTables_Real($ClassName, 1);
10372 if($Res==-1) {
10373 $Res = cmpVTables_Model($ClassName);
10374 }
10375 return $Res;
10376}
10377
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010378sub cmpVTables_Model($)
10379{
10380 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010381 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010382 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010383 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010384 return 1;
10385 }
10386 }
10387 return 0;
10388}
10389
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010390sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010391{
10392 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010393 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10394 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010395 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010396 my %VTable_Old = getVTable_Real($ClassName, 1);
10397 my %VTable_New = getVTable_Real($ClassName, 2);
10398 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010399 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010400 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010401 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010402 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010403 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10404 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010405 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010406 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010407 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010408 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010409 my $Entry1 = $VTable_Old{$Offset};
10410 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010411 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010412 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010413 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010414 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010415
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010416 $Entry1 = simpleVEntry($Entry1);
10417 $Entry2 = simpleVEntry($Entry2);
10418 if($Entry1 ne $Entry2)
10419 { # register as changed
10420 if($Entry1=~/::([^:]+)\Z/)
10421 {
10422 my $M1 = $1;
10423 if($Entry2=~/::([^:]+)\Z/)
10424 {
10425 my $M2 = $1;
10426 if($M1 eq $M2)
10427 { # overridden
10428 next;
10429 }
10430 }
10431 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010432 if(differentDumps("G"))
10433 {
10434 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10435 {
10436 # GCC 4.6.1: -0x00000000000000010
10437 # GCC 4.7.0: -16
10438 next;
10439 }
10440 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010441 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010442 }
10443 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010444 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010445}
10446
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010447sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010448{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010449 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010450 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10451 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010452 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010453 { # already registered
10454 next;
10455 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010456 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010457 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010458 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010459 foreach my $Symbol (@Affected)
10460 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010461 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010462 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010463 "Target"=>$ClassName);
10464 }
10465 }
10466 }
10467}
10468
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010469sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010470{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010471 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010472 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010473 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010474 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010475 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010476 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010477 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010478 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010479 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010480 if($TName_Tid{1}{$ClassName}
10481 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010482 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010483 if(defined $CompleteSignature{1}{$Symbol}
10484 and $CompleteSignature{1}{$Symbol}{"Virt"})
10485 { # override some method in v.1
10486 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010487 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010488 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010489 }
10490 }
10491 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010492 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010493 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010494 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010495 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010496 if($TName_Tid{2}{$ClassName}
10497 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010498 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010499 if(defined $CompleteSignature{2}{$Symbol}
10500 and $CompleteSignature{2}{$Symbol}{"Virt"})
10501 { # override some method in v.2
10502 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010503 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010504 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010505 }
10506 }
10507 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010508 if($Level eq "Binary")
10509 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010510 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010511 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10512 { # check replacements, including pure virtual methods
10513 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10514 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010515 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010516 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10517 if($AddedPos==$RemovedPos)
10518 {
10519 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10520 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10521 last; # other methods will be reported as "added" or "removed"
10522 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010523 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010524 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10525 {
10526 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10527 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010528 next;
10529 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010530 my $ProblemType = "Virtual_Replacement";
10531 my @Affected = ($RemovedVFunc);
10532 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10533 { # pure methods
10534 if(not isUsedClass($ClassId, 1, $Level))
10535 { # not a parameter of some exported method
10536 next;
10537 }
10538 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010539
10540 # affected all methods (both virtual and non-virtual ones)
10541 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10542 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010543 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010544 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010545 foreach my $AffectedInt (@Affected)
10546 {
10547 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10548 { # affected exported methods only
10549 next;
10550 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010551 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10552 next;
10553 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010554 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10555 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010556 "Target"=>get_Signature($AddedVFunc, 2),
10557 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10558 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010559 }
10560 }
10561 }
10562 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010563 if(not checkDump(1, "2.0")
10564 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010565 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010566 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010567 return;
10568 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010569 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010570 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010571 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010572 next if(not $ClassId_Old);
10573 if(not isCreatable($ClassId_Old, 1))
10574 { # skip classes without public constructors (including auto-generated)
10575 # example: class has only a private exported or private inline constructor
10576 next;
10577 }
10578 if($ClassName=~/>/)
10579 { # skip affected template instances
10580 next;
10581 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010582 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010583 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010584 if(not $ClassId_New) {
10585 next;
10586 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010587 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010588 if($Class_New{"Type"}!~/Class|Struct/)
10589 { # became typedef
10590 if($Level eq "Binary") {
10591 next;
10592 }
10593 if($Level eq "Source")
10594 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010595 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010596 if($Class_New{"Type"}!~/Class|Struct/) {
10597 next;
10598 }
10599 $ClassId_New = $Class_New{"Tid"};
10600 }
10601 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010602
10603 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10604 { # incomplete info in the ABI dump
10605 next;
10606 }
10607
10608
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010609 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10610 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 +040010611
10612 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10613 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10614
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010615 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010616 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10617 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010618 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10619 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010620 my $Shift_Old = getShift($ClassId_Old, 1);
10621 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010622 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010623 my ($Added, $Removed) = (0, 0);
10624 my @StableBases_Old = ();
10625 foreach my $BaseId (@Bases_Old)
10626 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010627 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010628 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010629 push(@StableBases_Old, $BaseId);
10630 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010631 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010632 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010633 { # removed base
10634 # excluding namespace::SomeClass to SomeClass renaming
10635 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010636 if($Level eq "Binary")
10637 { # Binary-level
10638 if($Shift_Old ne $Shift_New)
10639 { # affected fields
10640 if(havePubFields(\%Class_Old)) {
10641 $ProblemKind .= "_And_Shift";
10642 }
10643 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10644 $ProblemKind .= "_And_Size";
10645 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010646 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010647 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10648 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010649 { # affected v-table
10650 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010651 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010652 }
10653 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010654 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010655 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10656 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010657 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10658 {
10659 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10660 if($ProblemKind=~/VTable/) {
10661 $VTableChanged_M{$SubName}=1;
10662 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010663 }
10664 }
10665 foreach my $Interface (@Affected)
10666 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010667 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10668 next;
10669 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010670 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010671 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010672 "Target"=>$BaseName,
10673 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10674 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10675 "Shift"=>abs($Shift_New-$Shift_Old) );
10676 }
10677 $Removed+=1;
10678 }
10679 }
10680 my @StableBases_New = ();
10681 foreach my $BaseId (@Bases_New)
10682 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010683 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010684 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010685 push(@StableBases_New, $BaseId);
10686 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010687 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010688 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010689 { # added base
10690 # excluding namespace::SomeClass to SomeClass renaming
10691 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010692 if($Level eq "Binary")
10693 { # Binary-level
10694 if($Shift_Old ne $Shift_New)
10695 { # affected fields
10696 if(havePubFields(\%Class_Old)) {
10697 $ProblemKind .= "_And_Shift";
10698 }
10699 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10700 $ProblemKind .= "_And_Size";
10701 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010702 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010703 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10704 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010705 { # affected v-table
10706 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010707 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010708 }
10709 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010710 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010711 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10712 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010713 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10714 {
10715 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10716 if($ProblemKind=~/VTable/) {
10717 $VTableChanged_M{$SubName}=1;
10718 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010719 }
10720 }
10721 foreach my $Interface (@Affected)
10722 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010723 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10724 next;
10725 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010726 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010727 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010728 "Target"=>$BaseName,
10729 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10730 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10731 "Shift"=>abs($Shift_New-$Shift_Old) );
10732 }
10733 $Added+=1;
10734 }
10735 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010736 if($Level eq "Binary")
10737 { # Binary-level
10738 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010739 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10740 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010741 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010742 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010743 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010744 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010745 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010746 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10747 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010748 if($NewPos!=$OldPos)
10749 { # changed position of the base class
10750 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010751 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010752 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10753 next;
10754 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010755 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10756 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010757 "Target"=>$BaseName,
10758 "Old_Value"=>$OldPos-1,
10759 "New_Value"=>$NewPos-1 );
10760 }
10761 }
10762 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10763 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10764 { # became non-virtual base
10765 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10766 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010767 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10768 next;
10769 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010770 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10771 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010772 "Target"=>$BaseName );
10773 }
10774 }
10775 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10776 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10777 { # became virtual base
10778 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10779 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010780 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10781 next;
10782 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010783 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10784 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010785 "Target"=>$BaseName );
10786 }
10787 }
10788 }
10789 }
10790 # detect size changes in base classes
10791 if($Shift_Old!=$Shift_New)
10792 { # size of allocable class
10793 foreach my $BaseId (@StableBases_Old)
10794 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010795 my %BaseType = get_Type($BaseId, 1);
10796 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010797 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010798 if($Size_Old ne $Size_New
10799 and $Size_Old and $Size_New)
10800 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010801 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010802 if(isCopyingClass($BaseId, 1)) {
10803 $ProblemType = "Size_Of_Copying_Class";
10804 }
10805 elsif($AllocableClass{1}{$BaseType{"Name"}})
10806 {
10807 if($Size_New>$Size_Old)
10808 { # increased size
10809 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010810 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010811 else
10812 { # decreased size
10813 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10814 if(not havePubFields(\%Class_Old))
10815 { # affected class has no public members
10816 next;
10817 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010818 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010819 }
10820 next if(not $ProblemType);
10821 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10822 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010823 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10824 next;
10825 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010826 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10827 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010828 "Target"=>$BaseType{"Name"},
10829 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10830 "New_Size"=>$Size_New*$BYTE_SIZE );
10831 }
10832 }
10833 }
10834 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010835 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010836 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010837 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010838 { # compare virtual tables size in base classes
10839 my $VShift_Old = getVShift($ClassId_Old, 1);
10840 my $VShift_New = getVShift($ClassId_New, 2);
10841 if($VShift_Old ne $VShift_New)
10842 { # changes in the base class or changes in the list of base classes
10843 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10844 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10845 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010846 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010847 foreach my $BaseId (@AllBases_Old)
10848 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010849 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010850 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010851 { # lost base
10852 next;
10853 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010854 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10855 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010856 if($VSize_Old!=$VSize_New)
10857 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010858 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010859 { # TODO: affected non-virtual methods?
10860 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010861 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10862 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010863 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010864 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010865 { # skip interfaces that have not changed the absolute virtual position
10866 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010867 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010868 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10869 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010870 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010871 $VTableChanged_M{$BaseType{"Name"}} = 1;
10872 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010873 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10874 { # the reason of the layout change: added virtual functions
10875 next if($VirtualReplacement{$VirtFunc});
10876 my $ProblemType = "Added_Virtual_Method";
10877 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10878 $ProblemType = "Added_Pure_Virtual_Method";
10879 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010880 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010881 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010882 "Target"=>get_Signature($VirtFunc, 2) );
10883 }
10884 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
10885 { # the reason of the layout change: removed virtual functions
10886 next if($VirtualReplacement{$VirtFunc});
10887 my $ProblemType = "Removed_Virtual_Method";
10888 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
10889 $ProblemType = "Removed_Pure_Virtual_Method";
10890 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010891 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010892 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010893 "Target"=>get_Signature($VirtFunc, 1) );
10894 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010895 }
10896 }
10897 }
10898 }
10899 }
10900 }
10901 }
10902}
10903
10904sub isCreatable($$)
10905{
10906 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010907 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010908 or isCopyingClass($ClassId, $LibVersion)) {
10909 return 1;
10910 }
10911 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10912 { # Fix for incomplete data: if this class has
10913 # a base class then it should also has a constructor
10914 return 1;
10915 }
10916 if($ReturnedClass{$LibVersion}{$ClassId})
10917 { # returned by some method of this class
10918 # or any other class
10919 return 1;
10920 }
10921 return 0;
10922}
10923
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010924sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010925{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010926 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010927 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
10928 { # parameter of some exported method
10929 return 1;
10930 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010931 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
10932 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010933 { # method from target class
10934 return 1;
10935 }
10936 return 0;
10937}
10938
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010939sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010940{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010941 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010942 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010943 # - virtual
10944 # - pure-virtual
10945 # - non-virtual
10946 if($CompleteSignature{1}{$Interface}{"Data"})
10947 { # global data is not affected
10948 return;
10949 }
10950 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010951 if(not $Class_Id) {
10952 return;
10953 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010954 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010955 if(cmpVTables_Real($CName, 1)==0)
10956 { # no changes
10957 return;
10958 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010959 $CheckedTypes{$Level}{$CName} = 1;
10960 if($Level eq "Binary")
10961 { # Binary-level
10962 if($CompleteSignature{1}{$Interface}{"PureVirt"}
10963 and not isUsedClass($Class_Id, 1, $Level))
10964 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010965 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010966 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010967 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010968 }
10969 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
10970 {
10971 if(defined $VirtualTable{2}{$CName}{$Func}
10972 and defined $CompleteSignature{2}{$Func})
10973 {
10974 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
10975 and $CompleteSignature{2}{$Func}{"PureVirt"})
10976 { # became pure virtual
10977 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
10978 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010979 "Target"=>get_Signature_M($Func, 1) );
10980 $VTableChanged_M{$CName} = 1;
10981 }
10982 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
10983 and not $CompleteSignature{2}{$Func}{"PureVirt"})
10984 { # became non-pure virtual
10985 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
10986 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010987 "Target"=>get_Signature_M($Func, 1) );
10988 $VTableChanged_M{$CName} = 1;
10989 }
10990 }
10991 }
10992 if($Level eq "Binary")
10993 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010994 # check virtual table structure
10995 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
10996 {
10997 next if($Interface eq $AddedVFunc);
10998 next if($VirtualReplacement{$AddedVFunc});
10999 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11000 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11001 { # pure virtual methods affect all others (virtual and non-virtual)
11002 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011003 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011004 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011005 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011006 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011007 elsif(not defined $VirtualTable{1}{$CName}
11008 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011009 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011010 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011011 { # became polymorphous class, added v-table pointer
11012 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011013 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011014 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011015 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011016 }
11017 else
11018 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011019 my $VSize_Old = getVTable_Size($CName, 1);
11020 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011021 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011022 if(isCopyingClass($Class_Id, 1))
11023 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11024 my $ProblemType = "Added_Virtual_Method";
11025 if(isLeafClass($Class_Id, 1)) {
11026 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11027 }
11028 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11029 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011030 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011031 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011032 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011033 else
11034 {
11035 my $ProblemType = "Added_Virtual_Method";
11036 if(isLeafClass($Class_Id, 1)) {
11037 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11038 }
11039 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11040 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011041 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011042 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011043 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011044 }
11045 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011046 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11047 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011048 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011049 if(defined $VirtualTable{1}{$CName}
11050 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011051 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011052 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11053 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011054
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011055 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011056 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011057 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11058 foreach my $ASymbol (@Affected)
11059 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011060 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11061 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011062 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011063 next;
11064 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011065 }
11066 $CheckedSymbols{$Level}{$ASymbol} = 1;
11067 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11068 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011069 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011070 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011071 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011072 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011073 }
11074 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011075 else {
11076 # safe
11077 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011078 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011079 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11080 {
11081 next if($VirtualReplacement{$RemovedVFunc});
11082 if($RemovedVFunc eq $Interface
11083 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11084 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011085 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011086 next;
11087 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011088 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011089 { # became non-polymorphous class, removed v-table pointer
11090 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11091 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011092 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011093 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011094 }
11095 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11096 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11097 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011098 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011099 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011100 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11101 next;
11102 }
11103 my $VPos_New = -1;
11104 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011105 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011106 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11107 }
11108 else
11109 {
11110 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011111 next;
11112 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011113 }
11114 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11115 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11116 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11117 {
11118 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11119 foreach my $ASymbol (@Affected)
11120 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011121 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11122 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011123 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011124 next;
11125 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011126 }
11127 my $ProblemType = "Removed_Virtual_Method";
11128 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11129 $ProblemType = "Removed_Pure_Virtual_Method";
11130 }
11131 $CheckedSymbols{$Level}{$ASymbol} = 1;
11132 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11133 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011134 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011135 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011136 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011137 }
11138 }
11139 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011140 }
11141 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011142 else
11143 { # Source-level
11144 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011145 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011146 next if($Interface eq $AddedVFunc);
11147 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011148 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011149 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11150 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011151 "Target"=>get_Signature($AddedVFunc, 2) );
11152 }
11153 }
11154 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11155 {
11156 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11157 {
11158 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11159 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011160 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011161 }
11162 }
11163 }
11164}
11165
11166sub find_MemberPair_Pos_byName($$)
11167{
11168 my ($Member_Name, $Pair_Type) = @_;
11169 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11170 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11171 {
11172 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11173 {
11174 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11175 $Name=~s/\A[_]+|[_]+\Z//g;
11176 if($Name eq $Member_Name) {
11177 return $MemberPair_Pos;
11178 }
11179 }
11180 }
11181 return "lost";
11182}
11183
11184sub find_MemberPair_Pos_byVal($$)
11185{
11186 my ($Member_Value, $Pair_Type) = @_;
11187 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11188 {
11189 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11190 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11191 return $MemberPair_Pos;
11192 }
11193 }
11194 return "lost";
11195}
11196
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011197sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011198{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011199 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011200 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011201 if( $_->{"T1"} eq $_[0]
11202 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011203 {
11204 return 1;
11205 }
11206 }
11207 return 0;
11208}
11209
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011210sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011211{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011212 my %IDs = (
11213 "T1" => $_[0],
11214 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011215 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011216 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011217}
11218
11219sub isRenamed($$$$$)
11220{
11221 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11222 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11223 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011224 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011225 if(not defined $Type2->{"Memb"}{$MemPos}) {
11226 return "";
11227 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011228 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011229 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011230
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011231 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11232 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011233 if($MemberPair_Pos_Rev eq "lost")
11234 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011235 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11236 { # base type match
11237 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011238 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011239 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11240 { # exact type match
11241 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011242 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011243 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11244 { # size match
11245 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011246 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011247 if(isReserved($Pair_Name))
11248 { # reserved fields
11249 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011250 }
11251 }
11252 return "";
11253}
11254
11255sub isLastElem($$)
11256{
11257 my ($Pos, $TypeRef) = @_;
11258 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11259 if($Name=~/last|count|max|total/i)
11260 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11261 return 1;
11262 }
11263 elsif($Name=~/END|NLIMITS\Z/)
11264 { # __RLIMIT_NLIMITS
11265 return 1;
11266 }
11267 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11268 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11269 { # NImageFormats, NColorRoles
11270 return 1;
11271 }
11272 return 0;
11273}
11274
11275sub nonComparable($$)
11276{
11277 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011278
11279 my $N1 = $T1->{"Name"};
11280 my $N2 = $T2->{"Name"};
11281
11282 $N1=~s/\A(struct|union|enum) //;
11283 $N2=~s/\A(struct|union|enum) //;
11284
11285 if($N1 ne $N2
11286 and not isAnon($N1)
11287 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011288 { # different names
11289 if($T1->{"Type"} ne "Pointer"
11290 or $T2->{"Type"} ne "Pointer")
11291 { # compare base types
11292 return 1;
11293 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011294 if($N1!~/\Avoid\s*\*/
11295 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011296 {
11297 return 1;
11298 }
11299 }
11300 elsif($T1->{"Type"} ne $T2->{"Type"})
11301 { # different types
11302 if($T1->{"Type"} eq "Class"
11303 and $T2->{"Type"} eq "Struct")
11304 { # "class" to "struct"
11305 return 0;
11306 }
11307 elsif($T2->{"Type"} eq "Class"
11308 and $T1->{"Type"} eq "Struct")
11309 { # "struct" to "class"
11310 return 0;
11311 }
11312 else
11313 { # "class" to "enum"
11314 # "union" to "class"
11315 # ...
11316 return 1;
11317 }
11318 }
11319 return 0;
11320}
11321
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011322sub isOpaque($)
11323{
11324 my $T = $_[0];
11325 if(not defined $T->{"Memb"})
11326 {
11327 return 1;
11328 }
11329 return 0;
11330}
11331
11332sub removeVPtr($)
11333{ # support for old ABI dumps
11334 my $TPtr = $_[0];
11335 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11336 if($#Pos>=1)
11337 {
11338 foreach my $Pos (0 .. $#Pos-1)
11339 {
11340 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11341 }
11342 delete($TPtr->{"Memb"}{$#Pos});
11343 }
11344}
11345
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011346sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011347{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011348 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011349 return {} if(not $Type1_Id or not $Type2_Id);
11350
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011351 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011352 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011353 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011354 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011355
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011356 my %Type1 = get_Type($Type1_Id, 1);
11357 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011358 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011359 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011360 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011361
11362 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011363 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11364 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011365
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011366 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11367
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011368 my %SubProblems = ();
11369
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011370 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11371 {
11372 if($Type1_Pure{"Type"}=~/Struct|Union/
11373 and $Type2_Pure{"Type"}=~/Struct|Union/)
11374 {
11375 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11376 {
11377 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11378 "Target"=>$Type1_Pure{"Name"},
11379 "Type_Name"=>$Type1_Pure{"Name"} );
11380
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011381 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011382 }
11383 }
11384 }
11385
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011386 if(not $Type1_Pure{"Size"}
11387 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011388 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011389 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11390 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11391 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011392 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011393 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011394 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011395 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011396 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011397 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011398 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011399 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11400 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11401 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011402
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011403 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11404 { # support for old ABI dumps
11405 # _vptr field added in 3.0
11406 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11407 {
11408 if(defined $Type2_Pure{"Memb"}
11409 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11410 {
11411 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11412 delete($Type2_Pure{"Memb"}{0});
11413 }
11414 else {
11415 removeVPtr(\%Type2_Pure);
11416 }
11417 }
11418 }
11419 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11420 {
11421 if(defined $Type1_Pure{"Memb"}
11422 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11423 {
11424 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11425 delete($Type1_Pure{"Memb"}{0});
11426 }
11427 else {
11428 removeVPtr(\%Type1_Pure);
11429 }
11430 }
11431 }
11432 }
11433
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011434 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11435 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011436
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011437 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011438 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11439 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011440 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011441 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11442 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011443 if($Base_1{"Name"} ne $Base_2{"Name"})
11444 {
11445 if(differentDumps("G")
11446 or differentDumps("V"))
11447 { # different GCC versions or different dumps
11448 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11449 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11450 # std::__va_list and __va_list
11451 $Base_1{"Name"}=~s/\A(\w+::)+//;
11452 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011453 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11454 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011455 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011456 }
11457 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11458 and $Base_1{"Name"} ne $Base_2{"Name"})
11459 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011460 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011461 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011462 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011463 {
11464 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11465 "Target"=>$Typedef_1{"Name"},
11466 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011467 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11468 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11469 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011470 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11471 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011472 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011473 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011474 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11475 {
11476 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11477 "Target"=>$Typedef_1{"Name"},
11478 "Type_Name"=>$Typedef_1{"Name"},
11479 "Old_Value"=>$Base_1{"Name"},
11480 "New_Value"=>$Base_2{"Name"} );
11481 }
11482 else
11483 {
11484 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11485 "Target"=>$Typedef_1{"Name"},
11486 "Type_Name"=>$Typedef_1{"Name"},
11487 "Old_Value"=>$Base_1{"Name"},
11488 "New_Value"=>$Base_2{"Name"} );
11489 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011490 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011491 }
11492 }
11493 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11494 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011495 my $TT1 = $Type1_Pure{"Type"};
11496 my $TT2 = $Type2_Pure{"Type"};
11497
11498 if($TT1 ne $TT2
11499 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011500 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011501 my $Short1 = $Type1_Pure{"Name"};
11502 my $Short2 = $Type2_Pure{"Name"};
11503
11504 $Short1=~s/\A\Q$TT1\E //ig;
11505 $Short2=~s/\A\Q$TT2\E //ig;
11506
11507 if($Short1 eq $Short2)
11508 {
11509 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11510 "Target"=>$Type1_Pure{"Name"},
11511 "Type_Name"=>$Type1_Pure{"Name"},
11512 "Old_Value"=>lc($Type1_Pure{"Type"}),
11513 "New_Value"=>lc($Type2_Pure{"Type"}) );
11514 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011515 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011516 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011517 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011518 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011519 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11520 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11521 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11522 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011523 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011524 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011525 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011526 {
11527 my $ProblemKind = "DataType_Size";
11528 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011529 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011530 {
11531 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11532 $ProblemKind = "Size_Of_Copying_Class";
11533 }
11534 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11535 {
11536 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11537 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11538 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011539 else
11540 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011541 # descreased size of allocable class
11542 # it has no special effects
11543 }
11544 }
11545 }
11546 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11547 "Target"=>$Type1_Pure{"Name"},
11548 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011549 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011550 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011551 }
11552 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011553 if(defined $Type1_Pure{"BaseType"}
11554 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011555 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011556 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11557 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011558 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011559 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11560 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011561 }
11562 }
11563 }
11564 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11565 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11566 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11567 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11568 { # detect removed and renamed fields
11569 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11570 next if(not $Member_Name);
11571 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);
11572 if($MemberPair_Pos eq "lost")
11573 {
11574 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11575 {
11576 if(isUnnamed($Member_Name))
11577 { # support for old-version dumps
11578 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011579 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011580 next;
11581 }
11582 }
11583 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11584 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011585 $RenamedField{$Member_Pos} = $RenamedTo;
11586 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011587 }
11588 else
11589 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011590 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011591 }
11592 }
11593 elsif($Type1_Pure{"Type"} eq "Enum")
11594 {
11595 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11596 next if($Member_Value1 eq "");
11597 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11598 if($MemberPair_Pos ne "lost")
11599 { # renamed
11600 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11601 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11602 if($MemberPair_Pos_Rev eq "lost")
11603 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011604 $RenamedField{$Member_Pos} = $RenamedTo;
11605 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011606 }
11607 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011608 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011609 }
11610 }
11611 else
11612 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011613 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011614 }
11615 }
11616 }
11617 else
11618 { # related
11619 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11620 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11621 }
11622 }
11623 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11624 { # detect added fields
11625 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11626 next if(not $Member_Name);
11627 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);
11628 if($MemberPair_Pos eq "lost")
11629 {
11630 if(isUnnamed($Member_Name))
11631 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011632 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011633 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011634 next;
11635 }
11636 }
11637 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11638 {
11639 if(not $RenamedField_Rev{$Member_Pos})
11640 { # added
11641 $AddedField{$Member_Pos}=1;
11642 }
11643 }
11644 }
11645 }
11646 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11647 { # detect moved fields
11648 my (%RelPos, %RelPosName, %AbsPos) = ();
11649 my $Pos = 0;
11650 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11651 { # relative positions in 1st version
11652 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11653 next if(not $Member_Name);
11654 if(not $RemovedField{$Member_Pos})
11655 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011656 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011657 $RelPosName{1}{$Pos} = $Member_Name;
11658 $AbsPos{1}{$Pos++} = $Member_Pos;
11659 }
11660 }
11661 $Pos = 0;
11662 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11663 { # relative positions in 2nd version
11664 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11665 next if(not $Member_Name);
11666 if(not $AddedField{$Member_Pos})
11667 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011668 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011669 $RelPosName{2}{$Pos} = $Member_Name;
11670 $AbsPos{2}{$Pos++} = $Member_Pos;
11671 }
11672 }
11673 foreach my $Member_Name (keys(%{$RelPos{1}}))
11674 {
11675 my $RPos1 = $RelPos{1}{$Member_Name};
11676 my $AbsPos1 = $NameToPosA{$Member_Name};
11677 my $Member_Name2 = $Member_Name;
11678 if(my $RenamedTo = $RenamedField{$AbsPos1})
11679 { # renamed
11680 $Member_Name2 = $RenamedTo;
11681 }
11682 my $RPos2 = $RelPos{2}{$Member_Name2};
11683 if($RPos2 ne "" and $RPos1 ne $RPos2)
11684 { # different relative positions
11685 my $AbsPos2 = $NameToPosB{$Member_Name2};
11686 if($AbsPos1 ne $AbsPos2)
11687 { # different absolute positions
11688 my $ProblemType = "Moved_Field";
11689 if(not isPublic(\%Type1_Pure, $AbsPos1))
11690 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011691 if($Level eq "Source") {
11692 next;
11693 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011694 $ProblemType = "Moved_Private_Field";
11695 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011696 if($Level eq "Binary"
11697 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011698 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011699 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011700 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011701 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011702 if($MemSize1 ne $MemSize2) {
11703 $ProblemType .= "_And_Size";
11704 }
11705 }
11706 if($ProblemType eq "Moved_Private_Field") {
11707 next;
11708 }
11709 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11710 "Target"=>$Member_Name,
11711 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011712 "Old_Value"=>$RPos1,
11713 "New_Value"=>$RPos2 );
11714 }
11715 }
11716 }
11717 }
11718 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011719 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011720 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11721 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011722 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011723 if(my $RenamedTo = $RenamedField{$Member_Pos})
11724 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011725 if(defined $Constants{2}{$Member_Name})
11726 {
11727 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11728 { # define OLD NEW
11729 next; # Safe
11730 }
11731 }
11732
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011733 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11734 {
11735 if(isPublic(\%Type1_Pure, $Member_Pos))
11736 {
11737 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11738 "Target"=>$Member_Name,
11739 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011740 "Old_Value"=>$Member_Name,
11741 "New_Value"=>$RenamedTo );
11742 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011743 elsif(isReserved($Member_Name))
11744 {
11745 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11746 "Target"=>$Member_Name,
11747 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011748 "Old_Value"=>$Member_Name,
11749 "New_Value"=>$RenamedTo );
11750 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011751 }
11752 elsif($Type1_Pure{"Type"} eq "Enum")
11753 {
11754 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11755 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11756 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011757 "Old_Value"=>$Member_Name,
11758 "New_Value"=>$RenamedTo );
11759 }
11760 }
11761 elsif($RemovedField{$Member_Pos})
11762 { # removed
11763 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11764 {
11765 my $ProblemType = "Removed_Field";
11766 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011767 or isUnnamed($Member_Name))
11768 {
11769 if($Level eq "Source") {
11770 next;
11771 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011772 $ProblemType = "Removed_Private_Field";
11773 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011774 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011775 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011776 {
11777 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11778 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011779 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 +040011780 { # changed offset
11781 $ProblemType .= "_And_Layout";
11782 }
11783 }
11784 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11785 { # affected size
11786 $ProblemType .= "_And_Size";
11787 }
11788 }
11789 if($ProblemType eq "Removed_Private_Field") {
11790 next;
11791 }
11792 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11793 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011794 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011795 }
11796 elsif($Type2_Pure{"Type"} eq "Union")
11797 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011798 if($Level eq "Binary"
11799 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011800 {
11801 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11802 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011803 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011804 }
11805 else
11806 {
11807 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11808 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011809 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011810 }
11811 }
11812 elsif($Type1_Pure{"Type"} eq "Enum")
11813 {
11814 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11815 "Target"=>$Member_Name,
11816 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011817 "Old_Value"=>$Member_Name );
11818 }
11819 }
11820 else
11821 { # changed
11822 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11823 if($Type1_Pure{"Type"} eq "Enum")
11824 {
11825 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11826 next if($Member_Value1 eq "");
11827 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11828 next if($Member_Value2 eq "");
11829 if($Member_Value1 ne $Member_Value2)
11830 {
11831 my $ProblemType = "Enum_Member_Value";
11832 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11833 $ProblemType = "Enum_Last_Member_Value";
11834 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011835 if($SkipConstants{1}{$Member_Name}) {
11836 $ProblemType = "Enum_Private_Member_Value";
11837 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011838 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11839 "Target"=>$Member_Name,
11840 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011841 "Old_Value"=>$Member_Value1,
11842 "New_Value"=>$Member_Value2 );
11843 }
11844 }
11845 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11846 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011847 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
11848 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
11849
11850 if($Access1 ne "private"
11851 and $Access2 eq "private")
11852 {
11853 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
11854 "Target"=>$Member_Name,
11855 "Type_Name"=>$Type1_Pure{"Name"});
11856 }
11857 elsif($Access1 ne "protected"
11858 and $Access1 ne "private"
11859 and $Access2 eq "protected")
11860 {
11861 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
11862 "Target"=>$Member_Name,
11863 "Type_Name"=>$Type1_Pure{"Name"});
11864 }
11865
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011866 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
11867 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011868 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011869 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
11870 $SizeV1 = $BSize1;
11871 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011872 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011873 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
11874 $SizeV2 = $BSize2;
11875 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011876 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
11877 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011878 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011879 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011880 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011881 {
11882 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
11883 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
11884 { # field size change (including anon-structures and unions)
11885 # - same types
11886 # - unnamed types
11887 # - bitfields
11888 my $ProblemType = "Field_Size";
11889 if(not isPublic(\%Type1_Pure, $Member_Pos)
11890 or isUnnamed($Member_Name))
11891 { # should not be accessed by applications, goes to "Low Severity"
11892 # example: "abidata" members in GStreamer types
11893 $ProblemType = "Private_".$ProblemType;
11894 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011895 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 +040011896 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011897 if($Type2_Pure{"Type"} ne "Union"
11898 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011899 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011900 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 +040011901 { # changed offset
11902 $ProblemType .= "_And_Layout";
11903 }
11904 }
11905 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11906 $ProblemType .= "_And_Type_Size";
11907 }
11908 }
11909 if($ProblemType eq "Private_Field_Size")
11910 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011911 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040011912 if($ProblemType eq "Field_Size")
11913 {
11914 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
11915 { # Low severity
11916 $ProblemType = "Struct_Field_Size_Increased";
11917 }
11918 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011919 if($ProblemType)
11920 { # register a problem
11921 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11922 "Target"=>$Member_Name,
11923 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011924 "Old_Size"=>$SizeV1,
11925 "New_Size"=>$SizeV2);
11926 }
11927 }
11928 }
11929 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
11930 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
11931 { # do NOT check bitfield type changes
11932 next;
11933 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011934 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011935 {
11936 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
11937 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
11938 {
11939 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
11940 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011941 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011942 }
11943 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
11944 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
11945 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011946 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011947 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011948 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011949 }
11950 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011951 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
11952 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011953 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011954 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
11955 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011956
11957 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011958 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011959 or $ProblemType eq "Field_Type_And_Size"
11960 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011961 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011962 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011963 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011964 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011965 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011966 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011967 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011968 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011969 }
11970 }
11971 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
11972 {
11973 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011974 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011975 }
11976 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011977 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011978 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011979 }
11980 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
11981 {
11982 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011983 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011984 }
11985 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011986 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011987 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011988 }
11989 }
11990 }
11991
11992 if($Level eq "Source")
11993 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011994 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011995 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011996 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
11997 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011998
11999 if($ProblemType eq "Field_Type")
12000 {
12001 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012002 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012003 }
12004 }
12005 }
12006 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012007
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012008 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012009 {
12010 my $ProblemType_Init = $ProblemType;
12011 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012012 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012013 if(not isPublic(\%Type1_Pure, $Member_Pos)
12014 or isUnnamed($Member_Name)) {
12015 $ProblemType = "Private_".$ProblemType;
12016 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012017 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 +040012018 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012019 if($Type2_Pure{"Type"} ne "Union"
12020 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012021 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012022 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 +040012023 { # changed offset
12024 $ProblemType .= "_And_Layout";
12025 }
12026 }
12027 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12028 $ProblemType .= "_And_Type_Size";
12029 }
12030 }
12031 }
12032 else
12033 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012034 # TODO: Private_Field_Type rule?
12035
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012036 if(not isPublic(\%Type1_Pure, $Member_Pos)
12037 or isUnnamed($Member_Name)) {
12038 next;
12039 }
12040 }
12041 if($ProblemType eq "Private_Field_Type_And_Size")
12042 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012043 }
12044 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12045 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012046 "Type_Name"=>$Type1_Pure{"Name"});
12047
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012048 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012049 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012050 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012051 }
12052 }
12053 if(not isPublic(\%Type1_Pure, $Member_Pos))
12054 { # do NOT check internal type changes
12055 next;
12056 }
12057 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012058 { # checking member type changes
12059 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12060
12061 my %DupProblems = ();
12062
12063 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012064 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012065 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012066 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012067 if(not defined $AllAffected)
12068 {
12069 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12070 next;
12071 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012072 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012073
12074 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12075 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12076
12077 if(not defined $AllAffected)
12078 {
12079 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012080 }
12081 }
12082 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012083
12084 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012085 }
12086 }
12087 }
12088 }
12089 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12090 { # checking added members, public and private
12091 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12092 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012093 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012094 if($AddedField{$Member_Pos})
12095 { # added
12096 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12097 {
12098 my $ProblemType = "Added_Field";
12099 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012100 or isUnnamed($Member_Name))
12101 {
12102 if($Level eq "Source") {
12103 next;
12104 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012105 $ProblemType = "Added_Private_Field";
12106 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012107 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012108 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012109 {
12110 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12111 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012112 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 +040012113 { # changed offset
12114 $ProblemType .= "_And_Layout";
12115 }
12116 }
12117 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12118 $ProblemType .= "_And_Size";
12119 }
12120 }
12121 if($ProblemType eq "Added_Private_Field")
12122 { # skip added private fields
12123 next;
12124 }
12125 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12126 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012127 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012128 }
12129 elsif($Type2_Pure{"Type"} eq "Union")
12130 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012131 if($Level eq "Binary"
12132 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012133 {
12134 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12135 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012136 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012137 }
12138 else
12139 {
12140 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12141 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012142 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012143 }
12144 }
12145 elsif($Type2_Pure{"Type"} eq "Enum")
12146 {
12147 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12148 next if($Member_Value eq "");
12149 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12150 "Target"=>$Member_Name,
12151 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012152 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012153 }
12154 }
12155 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012156
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012157 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012158 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012159}
12160
12161sub isUnnamed($) {
12162 return $_[0]=~/\Aunnamed\d+\Z/;
12163}
12164
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012165sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012166{
12167 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012168 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12169 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12170 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12171 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012172 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012173 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012174 }
12175 return $TypeName;
12176}
12177
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012178sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012179{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012180 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012181 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012182 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12183 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012184 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012185 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12186 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012187 return () if(not $Type{"Type"});
12188 if($Type{"Type"} ne $Type_Type)
12189 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012190 return () if(not $Type{"BaseType"});
12191 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012192 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012193 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012194 return %Type;
12195}
12196
12197my %TypeSpecAttributes = (
12198 "Const" => 1,
12199 "Volatile" => 1,
12200 "ConstVolatile" => 1,
12201 "Restrict" => 1,
12202 "Typedef" => 1
12203);
12204
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012205sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012206{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012207 my ($TypeId, $Info) = @_;
12208 if(not $TypeId or not $Info
12209 or not $Info->{$TypeId}) {
12210 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012211 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012212 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12213 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12214 }
12215 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012216 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012217 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012218 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012219 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012220 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012221 return %Type;
12222}
12223
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012224sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012225{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012226 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012227 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012228 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12229 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012230 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012231 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12232 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012233 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12234 my $PLevel = 0;
12235 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12236 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012237 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012238 return $PLevel if(not $Type{"BaseType"});
12239 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12240 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12241 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012242}
12243
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012244sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012245{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012246 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012247 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012248 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12249 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012250 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012251 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12252 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012253 return %Type if(not $Type{"BaseType"});
12254 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012255 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012256 return %Type;
12257}
12258
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012259sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012260{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012261 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012262 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012263 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12264 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012265 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012266 my $Qual = "";
12267 if($Type{"Type"} eq "Pointer") {
12268 $Qual .= "*";
12269 }
12270 elsif($Type{"Type"} eq "Ref") {
12271 $Qual .= "&";
12272 }
12273 elsif($Type{"Type"} eq "ConstVolatile") {
12274 $Qual .= "const volatile";
12275 }
12276 elsif($Type{"Type"} eq "Const"
12277 or $Type{"Type"} eq "Volatile"
12278 or $Type{"Type"} eq "Restrict") {
12279 $Qual .= lc($Type{"Type"});
12280 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012281 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012282 return $BQual.$Qual;
12283}
12284
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012285sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012286{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012287 my ($TypeId, $Info) = @_;
12288 if(not $TypeId or not $Info
12289 or not $Info->{$TypeId}) {
12290 return ();
12291 }
12292 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012293 return %Type if(not $Type{"BaseType"});
12294 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012295 {
12296 if($Info->{$BTid}) {
12297 return %{$Info->{$BTid}};
12298 }
12299 else { # something is going wrong
12300 return ();
12301 }
12302 }
12303 else {
12304 return %Type;
12305 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012306}
12307
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012308sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012309{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012310 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012311 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012312 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12313 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012314}
12315
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012316sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012317{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012318 my $Symbol = $_[0];
12319 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12320}
12321
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012322sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012323 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12324}
12325
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012326sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012327{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012328 my ($SInfo, $LibVersion) = @_;
12329
12330 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012331 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012332 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012333 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012334 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012335 return 1;
12336 }
12337 }
12338 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012339 if(my $ShortName = $SInfo->{"ShortName"})
12340 {
12341 if(index($ShortName,"<")!=-1
12342 and index($ShortName,">")!=-1) {
12343 return 1;
12344 }
12345 }
12346
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012347 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012348}
12349
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012350sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012351{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012352 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012353 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012354 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012355 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012356 { # class specialization
12357 return 1;
12358 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012359 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012360 { # method specialization
12361 return 1;
12362 }
12363 }
12364 return 0;
12365}
12366
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012367sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012368{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012369 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012370
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012371 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012372 { # non-public global data
12373 return 0;
12374 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012375
12376 if(defined $SkipInternal)
12377 {
12378 return 0 if($Symbol=~/($SkipInternal)/);
12379 }
12380
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012381 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012382 { # support for old ABI dumps in --headers-only mode
12383 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12384 {
12385 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12386 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012387 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012388 if(not $PType or $PType eq "Unknown") {
12389 return 0;
12390 }
12391 }
12392 }
12393 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012394 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012395 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012396 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12397
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012398 if($SkipSymbols{$LibVersion}{$Symbol})
12399 { # user defined symbols to ignore
12400 return 0;
12401 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012402
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012403 if($SymbolsListPath and not $SymbolsList{$Symbol})
12404 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012405 if(not $TargetHeadersPath or not $Header
12406 or not is_target_header($Header, 1))
12407 { # -symbols-list | -headers-list
12408 return 0;
12409 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012410 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012411
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012412 if($AppPath and not $SymbolsList_App{$Symbol})
12413 { # user defined symbols (in application)
12414 return 0;
12415 }
12416
12417 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12418
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012419 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12420 if(not $NameSpace and $ClassId)
12421 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012422 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012423 }
12424 if($NameSpace)
12425 { # user defined namespaces to ignore
12426 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12427 return 0;
12428 }
12429 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12430 { # nested namespaces
12431 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12432 return 0;
12433 }
12434 }
12435 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012436 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012437 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012438 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012439 { # --skip-headers or <skip_headers> (not <skip_including>)
12440 if($Skip==1) {
12441 return 0;
12442 }
12443 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012444 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012445 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012446 { # user defined types
12447 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12448
12449 if(not $TypesList{$CName})
12450 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012451 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12452 {
12453 $CName=~s/\A\Q$NS\E\:\://g;
12454 }
12455
12456 if(not $TypesList{$CName})
12457 {
12458 my $Found = 0;
12459
12460 while($CName=~s/\:\:.+?\Z//)
12461 {
12462 if($TypesList{$CName})
12463 {
12464 $Found = 1;
12465 last;
12466 }
12467 }
12468
12469 if(not $Found) {
12470 return 0;
12471 }
12472 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012473 }
12474 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012475
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012476 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12477 { # non-target symbols
12478 return 0;
12479 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012480 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012481 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012482 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12483 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012484 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012485 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12486 { # inline virtual methods
12487 if($Type=~/InlineVirt/) {
12488 return 1;
12489 }
12490 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12491 if(not $Allocable)
12492 { # check bases
12493 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12494 {
12495 if(not isCopyingClass($DCId, $LibVersion))
12496 { # exists a derived class without default c-tor
12497 $Allocable=1;
12498 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012499 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012500 }
12501 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012502 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012503 return 0;
12504 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012505 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012506 else
12507 { # inline non-virtual methods
12508 return 0;
12509 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012510 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012511 }
12512 }
12513 return 1;
12514}
12515
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012516sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012517{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012518 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012519 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12520 {
12521 if(link_symbol($Symbol, 1, "+Deps"))
12522 { # linker can find a new symbol
12523 # in the old-version library
12524 # So, it's not a new symbol
12525 next;
12526 }
12527 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012528 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012529 next;
12530 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012531 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012532 }
12533}
12534
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012535sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012536{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012537 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012538 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12539 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012540 if(link_symbol($Symbol, 2, "+Deps"))
12541 { # linker can find an old symbol
12542 # in the new-version library
12543 next;
12544 }
12545 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012546 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012547 next;
12548 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012549 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012550 }
12551}
12552
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012553sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012554{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012555 my $Level = $_[0];
12556 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012557 { # checking added symbols
12558 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012559 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012560 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012561 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012562 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012563 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012564 { # checking removed symbols
12565 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012566 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012567 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012568 { # skip v-tables for templates, that should not be imported by applications
12569 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012570 if(my $CName = $VTableClass{$Symbol})
12571 {
12572 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12573 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012574 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012575 next;
12576 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012577 }
12578 }
12579 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012580 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012581 }
12582 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12583 { # symbols for pure virtual methods cannot be called by clients
12584 next;
12585 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012586 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012587 }
12588}
12589
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012590sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012591{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012592 my ($LibVersion, $V) = @_;
12593 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12594 return $Cache{"checkDump"}{$LibVersion}{$V};
12595 }
12596 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012597}
12598
12599sub detectAdded_H($)
12600{
12601 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012602 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12603 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012604 if($Level eq "Source")
12605 { # remove symbol version
12606 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12607 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012608
12609 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12610 { # skip artificial constructors
12611 next;
12612 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012613 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012614 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12615 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012616 next;
12617 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012618 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012619 next;
12620 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012621 if(not defined $CompleteSignature{1}{$Symbol}
12622 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12623 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012624 if($UsedDump{2}{"SrcBin"})
12625 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012626 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012627 { # support for old and different (!) ABI dumps
12628 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12629 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012630 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012631 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012632 {
12633 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12634 {
12635 if($Lang eq "C")
12636 { # support for old ABI dumps: missed extern "C" functions
12637 next;
12638 }
12639 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012640 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012641 else
12642 {
12643 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012644 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012645 next;
12646 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012647 }
12648 }
12649 }
12650 }
12651 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012652 }
12653 }
12654}
12655
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012656sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012657{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012658 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012659 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12660 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012661 if($Level eq "Source")
12662 { # remove symbol version
12663 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12664 $Symbol=$SN;
12665 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012666 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12667 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012668 next;
12669 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012670 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012671 next;
12672 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012673 if(not defined $CompleteSignature{2}{$Symbol}
12674 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012675 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012676 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012677 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012678 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012679 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012680 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12681 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012682 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012683 if($CheckHeadersOnly)
12684 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012685 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12686 {
12687 if($Lang eq "C")
12688 { # support for old ABI dumps: missed extern "C" functions
12689 next;
12690 }
12691 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012692 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012693 else
12694 {
12695 if(not link_symbol($Symbol, 1, "-Deps"))
12696 { # skip removed inline symbols
12697 next;
12698 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012699 }
12700 }
12701 }
12702 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012703 if(not checkDump(1, "2.15"))
12704 {
12705 if($Symbol=~/_IT_E\Z/)
12706 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12707 next;
12708 }
12709 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012710 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12711 {
12712 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12713 {
12714 if(defined $Constants{2}{$Short})
12715 {
12716 my $Val = $Constants{2}{$Short}{"Value"};
12717 if(defined $Func_ShortName{2}{$Val})
12718 { # old name defined to new
12719 next;
12720 }
12721 }
12722 }
12723
12724 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012725 $RemovedInt{$Level}{$Symbol} = 1;
12726 if($Level eq "Source")
12727 { # search for a source-compatible equivalent
12728 setAlternative($Symbol, $Level);
12729 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012730 }
12731 }
12732}
12733
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012734sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012735{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012736 my $Level = $_[0];
12737 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012738 { # checking added symbols
12739 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012740 next if($CompleteSignature{2}{$Symbol}{"Private"});
12741 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012742 if($Level eq "Binary")
12743 {
12744 if($CompleteSignature{2}{$Symbol}{"InLine"})
12745 {
12746 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12747 { # skip inline non-virtual functions
12748 next;
12749 }
12750 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012751 }
12752 else
12753 { # Source
12754 if($SourceAlternative_B{$Symbol}) {
12755 next;
12756 }
12757 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012758 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012759 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012760 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012761 { # checking removed symbols
12762 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012763 next if($CompleteSignature{1}{$Symbol}{"Private"});
12764 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012765 if($Level eq "Binary")
12766 {
12767 if($CompleteSignature{1}{$Symbol}{"InLine"})
12768 {
12769 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
12770 { # skip inline non-virtual functions
12771 next;
12772 }
12773 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012774 }
12775 else
12776 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012777 if(my $Alt = $SourceAlternative{$Symbol})
12778 {
12779 if(defined $CompleteSignature{1}{$Alt}
12780 and $CompleteSignature{1}{$Symbol}{"Const"})
12781 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012782 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012783 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012784 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012785 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012786 }
12787 else
12788 { # do NOT show removed symbol
12789 next;
12790 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012791 }
12792 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012793 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012794 }
12795}
12796
12797sub addParamNames($)
12798{
12799 my $LibraryVersion = $_[0];
12800 return if(not keys(%AddIntParams));
12801 my $SecondVersion = $LibraryVersion==1?2:1;
12802 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
12803 {
12804 next if(not keys(%{$AddIntParams{$Interface}}));
12805 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012806 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012807 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
12808 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012809 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012810 if(defined $CompleteSignature{$SecondVersion}{$Interface}
12811 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
12812 {
12813 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
12814 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12815 }
12816 }
12817 else {
12818 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12819 }
12820 }
12821 }
12822 }
12823}
12824
12825sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012826{ # detect changed typedefs to show
12827 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012828 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
12829 {
12830 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012831 my $BName1 = $Typedef_BaseName{1}{$Typedef};
12832 if(not $BName1 or isAnon($BName1)) {
12833 next;
12834 }
12835 my $BName2 = $Typedef_BaseName{2}{$Typedef};
12836 if(not $BName2 or isAnon($BName2)) {
12837 next;
12838 }
12839 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012840 $ChangedTypedef{$Typedef} = 1;
12841 }
12842 }
12843}
12844
12845sub get_symbol_suffix($$)
12846{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012847 my ($Symbol, $Full) = @_;
12848 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040012849 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012850 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012851 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012852 if(not $Full) {
12853 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
12854 }
12855 return $Suffix;
12856}
12857
12858sub get_symbol_prefix($$)
12859{
12860 my ($Symbol, $LibVersion) = @_;
12861 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
12862 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12863 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012864 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012865 }
12866 return $ShortName;
12867}
12868
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012869sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012870{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012871 my $Symbol = $_[0];
12872 my $PSymbol = $Symbol;
12873 if(not defined $CompleteSignature{2}{$PSymbol}
12874 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
12875 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
12876 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012877 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012878 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012879 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012880 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012881 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
12882 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012883 {
12884 if(defined $CompleteSignature{2}{$PSymbol}
12885 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12886 {
12887 $SourceAlternative{$Symbol} = $PSymbol;
12888 $SourceAlternative_B{$PSymbol} = $Symbol;
12889 if(not defined $CompleteSignature{1}{$PSymbol}
12890 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12891 $SourceReplacement{$Symbol} = $PSymbol;
12892 }
12893 }
12894 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012895 }
12896 else
12897 {
12898 foreach my $Sp ("KV", "VK", "K", "V")
12899 {
12900 if($PSymbol=~s/\A_ZN$Sp/_ZN/
12901 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
12902 {
12903 if(defined $CompleteSignature{2}{$PSymbol}
12904 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12905 {
12906 $SourceAlternative{$Symbol} = $PSymbol;
12907 $SourceAlternative_B{$PSymbol} = $Symbol;
12908 if(not defined $CompleteSignature{1}{$PSymbol}
12909 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12910 $SourceReplacement{$Symbol} = $PSymbol;
12911 }
12912 }
12913 }
12914 $PSymbol = $Symbol;
12915 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012916 }
12917 }
12918 }
12919 return "";
12920}
12921
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012922sub getSymKind($$)
12923{
12924 my ($Symbol, $LibVersion) = @_;
12925 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
12926 {
12927 return "Global_Data";
12928 }
12929 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12930 {
12931 return "Method";
12932 }
12933 return "Function";
12934}
12935
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040012936sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012937{
12938 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012939 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012940
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012941 mergeBases($Level);
12942
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012943 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012944 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012945 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012946 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012947 next;
12948 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012949 if(defined $CompleteSignature{1}{$Symbol}
12950 and $CompleteSignature{1}{$Symbol}{"Header"})
12951 { # double-check added symbol
12952 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012953 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012954 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012955 next;
12956 }
12957 if($Symbol=~/\A(_Z|\?)/)
12958 { # C++
12959 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
12960 }
12961 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
12962 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012963 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
12964 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012965 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012966 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012967 {
12968 if($TName_Tid{1}{$AffectedClass_Name})
12969 { # class should exist in previous version
12970 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
12971 { # old v-table is NOT copied by old applications
12972 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
12973 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012974 "Target"=>get_Signature($Symbol, 2),
12975 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012976 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012977 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012978 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012979 }
12980 }
12981 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012982 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
12983 { # check all removed exported symbols
12984 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012985 next;
12986 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012987 if(defined $CompleteSignature{2}{$Symbol}
12988 and $CompleteSignature{2}{$Symbol}{"Header"})
12989 { # double-check removed symbol
12990 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012991 }
12992 if($CompleteSignature{1}{$Symbol}{"Private"})
12993 { # skip private methods
12994 next;
12995 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012996 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012997 next;
12998 }
12999 $CheckedSymbols{$Level}{$Symbol} = 1;
13000 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13001 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013002 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13003 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013004 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013005 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13006 {
13007 if($TName_Tid{2}{$AffectedClass_Name})
13008 { # class should exist in newer version
13009 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13010 { # old v-table is NOT copied by old applications
13011 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13012 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013013 "Target"=>get_Signature($OverriddenMethod, 1),
13014 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013015 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013016 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013017 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013018 }
13019 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013020 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013021 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013022 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013023 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013024 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013025 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013026 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013027 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013028 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013029 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013030 {
13031 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13032 "Target"=>$tr_name{$Symbol},
13033 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013034 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013035 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013036 else
13037 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013038 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013039 "Target"=>$tr_name{$Symbol},
13040 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013041 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013042 }
13043 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013044 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013045 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013046 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013047 {
13048 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13049 "Target"=>$tr_name{$Symbol},
13050 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013051 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013052 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013053 else
13054 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013055 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013056 "Target"=>$tr_name{$Symbol},
13057 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013058 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013059 }
13060 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013061 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13062 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13063 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13064 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13065 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013066 {
13067 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013068 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013069 $ProblemType = "Global_Data_Symbol_Changed_Type";
13070 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013071 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13072 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013073 "Old_Type"=>$RTName1,
13074 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013075 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013076 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013077 }
13078 }
13079 }
13080 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013081 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013082 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013083 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013084 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013085 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013086 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013087 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013088 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13089 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013090 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013091 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013092 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013093 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013094 }
13095 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013096 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13097 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013098 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013099 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013100 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013101 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013102 }
13103 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013104 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013105 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013106 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013107 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013108 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013109 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013110 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013111 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013112 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013113 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013114 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013115 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013116 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013117 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013118 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013119 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013120 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013121 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013122 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013123 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013124 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013125 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013126 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013127 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013128 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013129 { # "volatile" to non-"volatile"
13130
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013131 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013132 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013133 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013134 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013135 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013136 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013137 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013138 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013139 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013140 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013141 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013142 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013143 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013144 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013145 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013146 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013147 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013148 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13149 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013150 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013151 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013152 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013153 }
13154 }
13155 }
13156 }
13157 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013158 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13159 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013160 $CurrentSymbol = $Symbol;
13161
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013162 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13163 if($Level eq "Source")
13164 { # remove symbol version
13165 $Symbol=$SN;
13166 }
13167 else
13168 { # Binary
13169 if(not $SV)
13170 { # symbol without version
13171 if(my $VSym = $SymVer{1}{$Symbol})
13172 { # the symbol is linked with versioned symbol
13173 if($CompleteSignature{2}{$VSym}{"MnglName"})
13174 { # show report for symbol@ver only
13175 next;
13176 }
13177 elsif(not link_symbol($VSym, 2, "-Deps"))
13178 { # changed version: sym@v1 to sym@v2
13179 # do NOT show report for symbol
13180 next;
13181 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013182 }
13183 }
13184 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013185 my $PSymbol = $Symbol;
13186 if($Level eq "Source"
13187 and my $S = $SourceReplacement{$Symbol})
13188 { # take a source-compatible replacement function
13189 $PSymbol = $S;
13190 }
13191 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013192 { # private symbols
13193 next;
13194 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013195 if(not defined $CompleteSignature{1}{$Symbol}
13196 or not defined $CompleteSignature{2}{$PSymbol})
13197 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013198 next;
13199 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013200 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13201 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13202 { # no mangled name
13203 next;
13204 }
13205 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13206 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013207 { # without a header
13208 next;
13209 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013210
13211 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13212 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13213 { # became pure
13214 next;
13215 }
13216 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13217 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13218 { # became non-pure
13219 next;
13220 }
13221
13222 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13223 { # exported, target, inline virtual and pure virtual
13224 next;
13225 }
13226 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13227 { # exported, target, inline virtual and pure virtual
13228 next;
13229 }
13230
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013231 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013232 {
13233 if($CompleteSignature{1}{$Symbol}{"Data"}
13234 and $CompleteSignature{2}{$PSymbol}{"Data"})
13235 {
13236 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13237 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13238 if(defined $Value1)
13239 {
13240 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13241 if(defined $Value2)
13242 {
13243 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13244 if($Value1 ne $Value2)
13245 {
13246 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13247 "Old_Value"=>$Value1,
13248 "New_Value"=>$Value2,
13249 "Target"=>get_Signature($Symbol, 1) );
13250 }
13251 }
13252 }
13253 }
13254 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013255
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013256 if($CompleteSignature{2}{$PSymbol}{"Private"})
13257 {
13258 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13259 "Target"=>get_Signature_M($PSymbol, 2) );
13260 }
13261 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13262 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13263 {
13264 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13265 "Target"=>get_Signature_M($PSymbol, 2) );
13266 }
13267 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13268 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13269 {
13270 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13271 "Target"=>get_Signature_M($PSymbol, 2) );
13272 }
13273
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013274 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013275 mergeVirtualTables($Symbol, $Level);
13276
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013277 if($COMPILE_ERRORS)
13278 { # if some errors occurred at the compiling stage
13279 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013280 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013281 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013282 { # missed information about parameters in newer version
13283 next;
13284 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013285 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013286 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013287 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013288 next;
13289 }
13290 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013291 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013292 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013293 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013294 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13295 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013296 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13297 "Target"=>get_Signature($Symbol, 1)
13298 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013299 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013300 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013301 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13302 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013303 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013304 "Target"=>get_Signature($Symbol, 1)
13305 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013306 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013307 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13308 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013309 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013310 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013311 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013312 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13313 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13314 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013315 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013316 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013317 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13318 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013319 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013320 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013321 my $ProblemType = "Virtual_Method_Position";
13322 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13323 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013324 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013325 if(isUsedClass($Class_Id, 1, $Level))
13326 {
13327 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013328 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013329 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013330 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13331 next;
13332 }
13333 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013334 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013335 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13336 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013337 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013338 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013339 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013340 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013341 }
13342 }
13343 }
13344 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013345 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13346 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013347 { # do NOT check type changes in pure virtuals
13348 next;
13349 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013350 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013351 if($Symbol=~/\A(_Z|\?)/
13352 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013353 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013354 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013355 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013356 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013357 }
13358 }
13359 else
13360 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013361 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013362 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013363 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013364 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13365 last if($PType2_Name eq "...");
13366 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13367 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013368 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013369 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013370 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013371 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13372 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013373 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13374 $ParamPos_Prev = "lost";
13375 }
13376 }
13377 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013378 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013379 }
13380 if($ParamPos_Prev eq "lost")
13381 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013382 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013383 {
13384 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013385 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013386 $ProblemType = "Added_Unnamed_Parameter";
13387 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013388 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013389 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013390 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013391 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013392 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013393 }
13394 else
13395 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013396 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013397 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013398 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013399 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13400 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013401 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013402 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013403 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013404 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013405 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013406 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013407 "Param_Type"=>$PType2_Name,
13408 "Old_Value"=>$PName_Old,
13409 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013410 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013411 }
13412 }
13413 else
13414 {
13415 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013416 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013417 $ProblemType = "Added_Middle_Unnamed_Parameter";
13418 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013419 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013420 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013421 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013422 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013423 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013424 }
13425 }
13426 }
13427 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013428 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013429 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013430 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013431 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013432 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013433 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013434 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013435 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013436 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013437 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13438 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013439 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013440 }
13441 }
13442 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013443 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013444 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013445 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013446 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13447 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013448 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13449 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013450 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013451 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013452 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013453 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13454 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013455 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13456 $ParamPos_New = "lost";
13457 }
13458 }
13459 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013460 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013461 }
13462 if($ParamPos_New eq "lost")
13463 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013464 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013465 {
13466 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013467 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013468 $ProblemType = "Removed_Unnamed_Parameter";
13469 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013470 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013471 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013472 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013473 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013474 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013475 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013476 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013477 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013478 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013479 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013480 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013481 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013482 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013483 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013484 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013485 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013486 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013487 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013488 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013489 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013490 "Old_Value"=>$PName,
13491 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013492 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013493 }
13494 }
13495 else
13496 {
13497 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013498 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013499 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13500 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013501 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013502 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013503 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013504 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013505 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013506 }
13507 }
13508 }
13509 }
13510 }
13511 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013512 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13513 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013514 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013515
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013516 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013517 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013518 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13519 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013520 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013521
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013522 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013523 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013524 if($SubProblemType eq "Return_Type_And_Size") {
13525 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13526 }
13527 elsif($SubProblemType eq "Return_Type_Format") {
13528 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13529 }
13530 else {
13531 $ProblemTypes{"Global_Data_Type"} = 1;
13532 }
13533
13534 # quals
13535 if($SubProblemType eq "Return_Type"
13536 or $SubProblemType eq "Return_Type_And_Size"
13537 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013538 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013539 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13540 { # const to non-const
13541 if($RR==2) {
13542 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13543 }
13544 else {
13545 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13546 }
13547 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013548 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013549 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13550 { # non-const to const
13551 if($RA==2) {
13552 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13553 }
13554 else {
13555 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13556 }
13557 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013558 }
13559 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013560 }
13561 else
13562 {
13563 # quals
13564 if($SubProblemType eq "Return_Type"
13565 or $SubProblemType eq "Return_Type_And_Size"
13566 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013567 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013568 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013569 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013570 if(addedQual($Old_Value, $New_Value, "volatile"))
13571 {
13572 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13573 if($Level ne "Source"
13574 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13575 $ProblemTypes{"Return_Type"} = 1;
13576 }
13577 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013578 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013579 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13580 {
13581 if($RA==2) {
13582 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13583 }
13584 else {
13585 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13586 }
13587 if($Level ne "Source"
13588 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13589 $ProblemTypes{"Return_Type"} = 1;
13590 }
13591 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013592 }
13593 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013594 if($Level eq "Binary"
13595 and not $CompleteSignature{1}{$Symbol}{"Data"})
13596 {
13597 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13598 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13599 { # if one of the architectures is unknown
13600 # then set other arhitecture to unknown too
13601 ($Arch1, $Arch2) = ("unknown", "unknown");
13602 }
13603 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013604 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013605 {
13606 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13607 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13608 }
13609 else
13610 {
13611 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13612 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13613 }
13614
13615 if($SubProblemType eq "Return_Type_Became_Void")
13616 {
13617 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13618 { # parameters stack has been affected
13619 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013620 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013621 }
13622 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013623 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013624 }
13625 }
13626 }
13627 elsif($SubProblemType eq "Return_Type_From_Void")
13628 {
13629 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13630 { # parameters stack has been affected
13631 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013632 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013633 }
13634 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013635 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013636 }
13637 }
13638 }
13639 elsif($SubProblemType eq "Return_Type"
13640 or $SubProblemType eq "Return_Type_And_Size"
13641 or $SubProblemType eq "Return_Type_Format")
13642 {
13643 if($Conv1{"Method"} ne $Conv2{"Method"})
13644 {
13645 if($Conv1{"Method"} eq "stack")
13646 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013647 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013648 }
13649 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013650 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013651 }
13652 }
13653 else
13654 {
13655 if($Conv1{"Method"} eq "reg")
13656 {
13657 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13658 {
13659 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013660 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013661 }
13662 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013663 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013664 }
13665 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013666 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013667 }
13668 }
13669 }
13670 }
13671 }
13672 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013673
13674 if(not keys(%ProblemTypes))
13675 { # default
13676 $ProblemTypes{$SubProblemType} = 1;
13677 }
13678
13679 foreach my $ProblemType (keys(%ProblemTypes))
13680 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013681 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013682 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013683 }
13684 if($ReturnType1_Id and $ReturnType2_Id)
13685 {
13686 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013687 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13688
13689 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013690
13691 if($CompleteSignature{1}{$Symbol}{"Data"})
13692 {
13693 if($Level eq "Binary")
13694 {
13695 if(get_PLevel($ReturnType1_Id, 1)==0)
13696 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013697 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013698 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013699
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013700 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13701 {
13702 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013703 {
13704 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13705 {
13706 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13707 last;
13708 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013709 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013710 }
13711 }
13712 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013713 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013714 {
13715 if(defined $GlobalDataObject{1}{$Symbol}
13716 and defined $GlobalDataObject{2}{$Symbol})
13717 {
13718 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13719 my $New_Size = $GlobalDataObject{2}{$Symbol};
13720 if($Old_Size!=$New_Size)
13721 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013722 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013723 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013724 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013725 }
13726 }
13727 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013728 }
13729 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013730
13731 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013732 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013733 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013734 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013735 my $NewLocation = "retval";
13736 if($SubLocation and $SubLocation ne "retval") {
13737 $NewLocation = "retval->".$SubLocation;
13738 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013739 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13740 }
13741 }
13742
13743 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13744 {
13745 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
13746 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013747 my $NewLocation = "retval";
13748 if($SubLocation and $SubLocation ne "retval") {
13749 $NewLocation = "retval->".$SubLocation;
13750 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013751 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013752 }
13753 }
13754 }
13755
13756 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013757 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13758 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13759 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013760 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013761 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013762 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13763 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013764 if($ThisPtr1_Id and $ThisPtr2_Id)
13765 {
13766 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013767 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
13768 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013769 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013770 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013771 {
13772 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013773 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013774 }
13775 }
13776 }
13777 }
13778 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013779 if($Level eq "Binary") {
13780 mergeVTables($Level);
13781 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013782 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
13783 $CheckedSymbols{$Level}{$Symbol} = 1;
13784 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013785}
13786
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013787sub rmQuals($$)
13788{
13789 my ($Value, $Qual) = @_;
13790 if(not $Qual) {
13791 return $Value;
13792 }
13793 if($Qual eq "all")
13794 { # all quals
13795 $Qual = "const|volatile|restrict";
13796 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013797 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013798 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013799 }
13800 return $Value;
13801}
13802
13803sub cmpBTypes($$$$)
13804{
13805 my ($T1, $T2, $V1, $V2) = @_;
13806 $T1 = uncover_typedefs($T1, $V1);
13807 $T2 = uncover_typedefs($T2, $V2);
13808 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
13809}
13810
13811sub addedQual($$$)
13812{
13813 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013814 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013815}
13816
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013817sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013818{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013819 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013820 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013821}
13822
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013823sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013824{
13825 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
13826 $Old_Value = uncover_typedefs($Old_Value, $V1);
13827 $New_Value = uncover_typedefs($New_Value, $V2);
13828 if($Old_Value eq $New_Value)
13829 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013830 return 0;
13831 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013832 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013833 { # without a qual
13834 return 0;
13835 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013836 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013837 { # became non-qual
13838 return 1;
13839 }
13840 else
13841 {
13842 my @BQ1 = getQualModel($Old_Value, $Qual);
13843 my @BQ2 = getQualModel($New_Value, $Qual);
13844 foreach (0 .. $#BQ1)
13845 { # removed qual
13846 if($BQ1[$_]==1
13847 and $BQ2[$_]!=1)
13848 {
13849 return 2;
13850 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013851 }
13852 }
13853 return 0;
13854}
13855
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013856sub getQualModel($$)
13857{
13858 my ($Value, $Qual) = @_;
13859 if(not $Qual) {
13860 return $Value;
13861 }
13862
13863 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013864 while($Value=~/(\w+)/ and $1 ne $Qual) {
13865 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013866 }
13867 $Value=~s/[^\*\&\w]+//g;
13868
13869 # modeling
13870 # int*const*const == 011
13871 # int**const == 001
13872 my @Model = ();
13873 my @Elems = split(/[\*\&]/, $Value);
13874 if(not @Elems) {
13875 return (0);
13876 }
13877 foreach (@Elems)
13878 {
13879 if($_ eq $Qual) {
13880 push(@Model, 1);
13881 }
13882 else {
13883 push(@Model, 0);
13884 }
13885 }
13886
13887 return @Model;
13888}
13889
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013890my %StringTypes = map {$_=>1} (
13891 "char*",
13892 "char const*"
13893);
13894
13895my %CharTypes = map {$_=>1} (
13896 "char",
13897 "char const"
13898);
13899
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013900sub showVal($$$)
13901{
13902 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013903 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040013904 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040013905 if(substr($Value, 0, 2) eq "_Z")
13906 {
13907 if(my $Unmangled = $tr_name{$Value}) {
13908 return $Unmangled;
13909 }
13910 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013911 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013912 { # strings
13913 return "\"$Value\"";
13914 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013915 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013916 { # characters
13917 return "\'$Value\'";
13918 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013919 if($Value eq "")
13920 { # other
13921 return "\'\'";
13922 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013923 return $Value;
13924}
13925
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013926sub getRegs($$$)
13927{
13928 my ($LibVersion, $Symbol, $Pos) = @_;
13929
13930 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
13931 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013932 my %Regs = ();
13933 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
13934 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013935 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013936 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
13937 }
13938 }
13939
13940 return join(", ", sort keys(%Regs));
13941 }
13942
13943 return undef;
13944}
13945
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013946sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013947{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013948 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013949 if(not $Symbol) {
13950 return;
13951 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013952 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
13953 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
13954 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
13955 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013956 if(not $PType1_Id
13957 or not $PType2_Id) {
13958 return;
13959 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013960
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013961 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040013962 { # do not merge "this"
13963 if($PName1 eq "this" or $PName2 eq "this") {
13964 return;
13965 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013966 }
13967
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013968 my %Type1 = get_Type($PType1_Id, 1);
13969 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030013970
13971 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
13972
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013973 my %BaseType1 = get_BaseType($PType1_Id, 1);
13974 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030013975
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013976 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013977
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013978 if($Level eq "Binary")
13979 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013980 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013981 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
13982 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
13983 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
13984 {
13985 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013986 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013987 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013988 }
13989 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
13990 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
13991 {
13992 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013993 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013994 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013995 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013996 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013997
13998 if(defined $UsedDump{1}{"DWARF"}
13999 and defined $UsedDump{2}{"DWARF"})
14000 {
14001 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14002 {
14003 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14004 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
14005 if($Old_Regs and $New_Regs)
14006 {
14007 if($Old_Regs ne $New_Regs)
14008 {
14009 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14010 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014011 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014012 "Old_Value"=>$Old_Regs,
14013 "New_Value"=>$New_Regs );
14014 }
14015 }
14016 elsif($Old_Regs and not $New_Regs)
14017 {
14018 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
14019 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014020 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014021 "Old_Value"=>$Old_Regs );
14022 }
14023 elsif(not $Old_Regs and $New_Regs)
14024 {
14025 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14026 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014027 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014028 "New_Value"=>$New_Regs );
14029 }
14030 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14031 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14032 {
14033 if($Old_Offset ne $New_Offset)
14034 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014035 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14036 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14037
14038 $Old_Offset = $Old_Offset - $Start1;
14039 $New_Offset = $New_Offset - $Start2;
14040
14041 if($Old_Offset ne $New_Offset)
14042 {
14043 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14044 "Target"=>$PName1,
14045 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14046 "Old_Value"=>$Old_Offset,
14047 "New_Value"=>$New_Offset );
14048 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014049 }
14050 }
14051 }
14052 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014053 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014054 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14055 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014056 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014057 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014058 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14059 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014060 if(not checkDump(1, "2.13")
14061 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014062 { # support for old ABI dumps
14063 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014064 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014065 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014066 and $Value_Old eq "false" and $Value_New eq "0")
14067 { # int class::method ( bool p = 0 );
14068 # old ABI dumps: "false"
14069 # new ABI dumps: "0"
14070 $Value_Old = "0";
14071 }
14072 }
14073 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014074 if(not checkDump(1, "2.18")
14075 and checkDump(2, "2.18"))
14076 { # support for old ABI dumps
14077 if(not defined $Value_Old
14078 and substr($Value_New, 0, 2) eq "_Z") {
14079 $Value_Old = $Value_New;
14080 }
14081 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014082 if(defined $Value_Old)
14083 {
14084 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14085 if(defined $Value_New)
14086 {
14087 $Value_New = showVal($Value_New, $PType2_Id, 2);
14088 if($Value_Old ne $Value_New)
14089 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014090 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014091 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014092 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014093 "Old_Value"=>$Value_Old,
14094 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014095 }
14096 }
14097 else
14098 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014099 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014100 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014101 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014102 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014103 }
14104 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014105 elsif(defined $Value_New)
14106 {
14107 $Value_New = showVal($Value_New, $PType2_Id, 2);
14108 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14109 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014110 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014111 "New_Value"=>$Value_New );
14112 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014113 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014114
14115 if($ChkRnmd)
14116 {
14117 if($PName1 and $PName2 and $PName1 ne $PName2
14118 and $PType1_Id!=-1 and $PType2_Id!=-1
14119 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14120 { # except unnamed "..." value list (Id=-1)
14121 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14122 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014123 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014124 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14125 "Old_Value"=>$PName1,
14126 "New_Value"=>$PName2,
14127 "New_Signature"=>get_Signature($Symbol, 2) );
14128 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014129 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014130
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014131 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014132 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014133
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014134 foreach my $SubProblemType (keys(%SubProblems))
14135 { # add new problems, remove false alarms
14136 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14137 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014138
14139 # quals
14140 if($SubProblemType eq "Parameter_Type"
14141 or $SubProblemType eq "Parameter_Type_And_Size"
14142 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014143 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014144 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014145 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014146 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014147 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014148 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014149 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14150 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14151 }
14152 }
14153 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14154 {
14155 if(removedQual($Old_Value, $New_Value, "volatile")) {
14156 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014157 }
14158 }
14159 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14160 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14161 { # int to "int const"
14162 delete($SubProblems{$SubProblemType});
14163 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014164 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014165 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14166 { # "int const" to int
14167 delete($SubProblems{$SubProblemType});
14168 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014169 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14170 { # "const" to non-"const"
14171 if($RR==2) {
14172 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14173 }
14174 else {
14175 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14176 }
14177 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014178 }
14179 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014180
14181 if($Level eq "Source")
14182 {
14183 foreach my $SubProblemType (keys(%SubProblems))
14184 {
14185 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14186 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14187
14188 if($SubProblemType eq "Parameter_Type")
14189 {
14190 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14191 delete($SubProblems{$SubProblemType});
14192 }
14193 }
14194 }
14195 }
14196
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014197 foreach my $SubProblemType (keys(%SubProblems))
14198 { # modify/register problems
14199 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14200 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014201 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14202 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014203
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014204 my $NewProblemType = $SubProblemType;
14205 if($Old_Value eq "..." and $New_Value ne "...")
14206 { # change from "..." to "int"
14207 if($ParamPos1==0)
14208 { # ISO C requires a named argument before "..."
14209 next;
14210 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014211 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014212 }
14213 elsif($New_Value eq "..." and $Old_Value ne "...")
14214 { # change from "int" to "..."
14215 if($ParamPos2==0)
14216 { # ISO C requires a named argument before "..."
14217 next;
14218 }
14219 $NewProblemType = "Parameter_Became_VaList";
14220 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014221 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014222 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014223 {
14224 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014225 if($Arch1 eq "unknown"
14226 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014227 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014228 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014229 ($Arch1, $Arch2) = ("unknown", "unknown");
14230 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014231 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014232 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014233 { # real
14234 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14235 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14236 }
14237 else
14238 { # model
14239 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14240 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14241 }
14242 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014243 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014244 if($Conv1{"Method"} eq "stack")
14245 {
14246 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14247 $NewProblemType = "Parameter_Type_And_Stack";
14248 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014249 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014250 elsif($Conv1{"Method"} eq "reg")
14251 {
14252 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14253 $NewProblemType = "Parameter_Type_And_Register";
14254 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014255 }
14256 }
14257 else
14258 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014259 if($Conv1{"Method"} eq "stack") {
14260 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014261 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014262 elsif($Conv1{"Method"} eq "register") {
14263 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014264 }
14265 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014266 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14267 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014268 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014269 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014270 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014271 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014272 "New_Signature"=>get_Signature($Symbol, 2) );
14273 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014274 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014275
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014276 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014277
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014278 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014279 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14280 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014281 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014282 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014283 {
14284 my $NewProblemType = $SubProblemType;
14285 if($SubProblemType eq "DataType_Size")
14286 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014287 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014288 { # stack has been affected
14289 $NewProblemType = "DataType_Size_And_Stack";
14290 }
14291 }
14292 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014293 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014294 }
14295 }
14296}
14297
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014298sub find_ParamPair_Pos_byName($$$)
14299{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014300 my ($Name, $Symbol, $LibVersion) = @_;
14301 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014302 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014303 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14304 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014305 {
14306 return $ParamPos;
14307 }
14308 }
14309 return "lost";
14310}
14311
14312sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14313{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014314 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014315 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014316 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014317 {
14318 next if($Order eq "backward" and $ParamPos>$MediumPos);
14319 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014320 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14321 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014322 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014323 push(@Positions, $ParamPos);
14324 }
14325 }
14326 return @Positions;
14327}
14328
14329sub getTypeIdByName($$)
14330{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014331 my ($TypeName, $LibVersion) = @_;
14332 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014333}
14334
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014335sub diffTypes($$$)
14336{
14337 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14338 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14339 }
14340 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14341 { # skip recursive declarations
14342 return 0;
14343 }
14344
14345 pushType($_[0], $_[1], \@RecurTypes_Diff);
14346 my $Diff = diffTypes_I(@_);
14347 pop(@RecurTypes_Diff);
14348
14349 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14350}
14351
14352sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014353{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014354 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014355
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014356 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14357 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014358
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014359 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14360 { # equal types
14361 return 0;
14362 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014363 if($Type1_Pure{"Name"} eq "void")
14364 { # from void* to something
14365 return 0;
14366 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014367 if($Type1_Pure{"Name"}=~/\*/
14368 or $Type2_Pure{"Name"}=~/\*/)
14369 { # compared in detectTypeChange()
14370 return 0;
14371 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014372
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014373 my %FloatType = map {$_=>1} (
14374 "float",
14375 "double",
14376 "long double"
14377 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014378
14379 my $T1 = $Type1_Pure{"Type"};
14380 my $T2 = $Type2_Pure{"Type"};
14381
14382 if($T1 eq "Struct"
14383 and $T2 eq "Class")
14384 { # compare as data structures
14385 $T2 = "Struct";
14386 }
14387
14388 if($T1 eq "Class"
14389 and $T2 eq "Struct")
14390 { # compare as data structures
14391 $T1 = "Struct";
14392 }
14393
14394 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014395 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014396 if($T1 eq "Intrinsic"
14397 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014398 { # "int" to "enum"
14399 return 0;
14400 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014401 elsif($T2 eq "Intrinsic"
14402 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014403 { # "enum" to "int"
14404 return 0;
14405 }
14406 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014407 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014408 # ...
14409 return 1;
14410 }
14411 }
14412 else
14413 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014414 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014415 {
14416 if($FloatType{$Type1_Pure{"Name"}}
14417 or $FloatType{$Type2_Pure{"Name"}})
14418 { # "float" to "double"
14419 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014420 if($Level eq "Source")
14421 { # Safe
14422 return 0;
14423 }
14424 else {
14425 return 1;
14426 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014427 }
14428 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014429 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014430 {
14431 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14432 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014433 if(not @Membs1
14434 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014435 { # private
14436 return 0;
14437 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014438 if($#Membs1!=$#Membs2)
14439 { # different number of elements
14440 return 1;
14441 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014442 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014443 {
14444 foreach my $Pos (@Membs1)
14445 { # compare elements by name and value
14446 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14447 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14448 { # different names
14449 return 1;
14450 }
14451 }
14452 }
14453 else
14454 {
14455 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014456 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014457 if($Level eq "Source")
14458 {
14459 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14460 { # different names
14461 return 1;
14462 }
14463 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014464
14465 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14466 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14467
14468 if($MT1{"Name"} ne $MT2{"Name"}
14469 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14470 {
14471 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14472 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14473
14474 if($PL1 ne $PL2)
14475 { # different pointer level
14476 return 1;
14477 }
14478
14479 # compare base types
14480 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14481 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14482
14483 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14484 { # different types
14485 return 1;
14486 }
14487 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014488 }
14489 }
14490 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014491 else
14492 {
14493 # TODO: arrays, etc.
14494 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014495 }
14496 return 0;
14497}
14498
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014499sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014500{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014501 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014502 if(not $Type1_Id or not $Type2_Id) {
14503 return ();
14504 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014505 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014506 my %Type1 = get_Type($Type1_Id, 1);
14507 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014508 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14509 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14510 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14511 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 +040014512
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014513 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14514 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014515 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14516 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14517 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14518 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14519 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14520 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14521 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014522 if($Type1{"Name"} eq $Type2{"Name"})
14523 {
14524 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14525 { # will be reported in mergeTypes() as typedef problem
14526 return ();
14527 }
14528 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14529 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14530 if(%Typedef_1 and %Typedef_2)
14531 {
14532 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14533 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14534 { # const Typedef
14535 return ();
14536 }
14537 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014538 }
14539 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14540 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014541 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014542 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14543 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014544 {
14545 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14546 "Old_Value"=>$Type1_Base{"Name"},
14547 "New_Value"=>$Type2_Base{"Name"},
14548 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014549 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014550 }
14551 else
14552 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014553 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014554 { # format change
14555 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14556 "Old_Value"=>$Type1_Base{"Name"},
14557 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014558 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014559 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014560 }
14561 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14562 {
14563 %{$LocalProblems{$Prefix."_BaseType"}}=(
14564 "Old_Value"=>$Type1_Base{"Name"},
14565 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014566 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014567 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014568 }
14569 }
14570 }
14571 }
14572 elsif($Type1{"Name"} ne $Type2{"Name"})
14573 { # type change
14574 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14575 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014576 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014577 and $Type1_Pure{"Name"} eq "void")
14578 {
14579 %{$LocalProblems{"Return_Type_From_Void"}}=(
14580 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014581 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014582 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014583 elsif($Prefix eq "Return"
14584 and $Type2_Pure{"Name"} eq "void")
14585 {
14586 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14587 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014588 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014589 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014590 else
14591 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014592 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014593 and $Type1{"Size"} and $Type2{"Size"}
14594 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014595 {
14596 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14597 "Old_Value"=>$Type1{"Name"},
14598 "New_Value"=>$Type2{"Name"},
14599 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014600 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014601 }
14602 else
14603 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014604 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014605 { # format change
14606 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14607 "Old_Value"=>$Type1{"Name"},
14608 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014609 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014610 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014611 }
14612 elsif(tNameLock($Type1_Id, $Type2_Id))
14613 { # FIXME: correct this condition
14614 %{$LocalProblems{$Prefix."_Type"}}=(
14615 "Old_Value"=>$Type1{"Name"},
14616 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014617 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014618 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014619 }
14620 }
14621 }
14622 }
14623 }
14624 if($Type1_PLevel!=$Type2_PLevel)
14625 {
14626 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14627 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14628 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014629 if($Level eq "Source")
14630 {
14631 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014632 "Old_Value"=>$Type1_PLevel,
14633 "New_Value"=>$Type2_PLevel);
14634 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014635 else
14636 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014637 if($Type2_PLevel>$Type1_PLevel)
14638 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014639 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14640 "Old_Value"=>$Type1_PLevel,
14641 "New_Value"=>$Type2_PLevel);
14642 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014643 else
14644 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014645 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14646 "Old_Value"=>$Type1_PLevel,
14647 "New_Value"=>$Type2_PLevel);
14648 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014649 }
14650 }
14651 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014652 if($Type1_Pure{"Type"} eq "Array"
14653 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014654 { # base_type[N] -> base_type[N]
14655 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014656 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014657 foreach my $SubProblemType (keys(%SubProblems))
14658 {
14659 $SubProblemType=~s/_Type/_BaseType/g;
14660 next if(defined $LocalProblems{$SubProblemType});
14661 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14662 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14663 }
14664 }
14665 }
14666 return %LocalProblems;
14667}
14668
14669sub tNameLock($$)
14670{
14671 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014672 my $Changed = 0;
14673 if(differentDumps("G"))
14674 { # different GCC versions
14675 $Changed = 1;
14676 }
14677 elsif(differentDumps("V"))
14678 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014679 if(not checkDump(1, "2.20")
14680 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014681 { # latest names update
14682 # 2.6: added restrict qualifier
14683 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014684 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014685 $Changed = 1;
14686 }
14687 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014688
14689 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14690 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14691
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014692 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14693 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14694
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014695 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014696 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014697 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014698 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014699 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014700 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014701 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014702 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014703 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014704 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014705 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14706 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14707 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014708 { # equal base types
14709 return 0;
14710 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014711
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014712 if(not checkDump(1, "2.13")
14713 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014714 { # broken array names in ABI dumps < 2.13
14715 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014716 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014717 return 0;
14718 }
14719 }
14720
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014721 if(not checkDump(1, "2.6")
14722 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014723 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014724 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014725 and $TN2=~/\brestrict\b/) {
14726 return 0;
14727 }
14728 }
14729
14730 if(not checkDump(1, "2.20")
14731 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014732 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014733 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14734 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014735 return 0;
14736 }
14737 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014738 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014739 else
14740 {
14741 # typedef struct {...} type_t
14742 # typedef struct type_t {...} type_t
14743 if(index($TN1, " ".$TN2)!=-1)
14744 {
14745 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
14746 return 0;
14747 }
14748 }
14749 if(index($TN2, " ".$TN1)!=-1)
14750 {
14751 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
14752 return 0;
14753 }
14754 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014755
14756 if($TT1 eq "FuncPtr"
14757 and $TT2 eq "FuncPtr")
14758 {
14759 my $TN1_C = $TN1;
14760 my $TN2_C = $TN2;
14761
14762 $TN1_C=~s/\b(struct|union) //g;
14763 $TN2_C=~s/\b(struct|union) //g;
14764
14765 if($TN1_C eq $TN2_C) {
14766 return 0;
14767 }
14768 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014769 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014770
14771 my ($N1, $N2) = ($TN1, $TN2);
14772 $N1=~s/\b(struct|union) //g;
14773 $N2=~s/\b(struct|union) //g;
14774
14775 if($N1 eq $N2)
14776 { # QList<struct QUrl> and QList<QUrl>
14777 return 0;
14778 }
14779
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014780 return 1;
14781}
14782
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014783sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014784{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014785 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014786 if(defined $Cache{"differentDumps"}{$Check}) {
14787 return $Cache{"differentDumps"}{$Check};
14788 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014789 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014790 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014791 if($Check eq "G")
14792 {
14793 if(getGccVersion(1) ne getGccVersion(2))
14794 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014795 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014796 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014797 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014798 if($Check eq "V")
14799 {
14800 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
14801 formatVersion($UsedDump{2}{"V"}, 2))!=0)
14802 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014803 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014804 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014805 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014806 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014807 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014808}
14809
14810sub formatVersion($$)
14811{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014812 my ($V, $Digits) = @_;
14813 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014814 return join(".", splice(@Elems, 0, $Digits));
14815}
14816
14817sub htmlSpecChars($)
14818{
14819 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014820 if(not $Str) {
14821 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014822 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014823 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14824 $Str=~s/</&lt;/g;
14825 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
14826 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014827 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
14828 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014829 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014830 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014831 $Str=~s/\n/<br\/>/g;
14832 $Str=~s/\"/&quot;/g;
14833 $Str=~s/\'/&#39;/g;
14834 return $Str;
14835}
14836
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014837sub xmlSpecChars($)
14838{
14839 my $Str = $_[0];
14840 if(not $Str) {
14841 return $Str;
14842 }
14843
14844 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14845 $Str=~s/</&lt;/g;
14846 $Str=~s/>/&gt;/g;
14847
14848 $Str=~s/\"/&quot;/g;
14849 $Str=~s/\'/&#39;/g;
14850
14851 return $Str;
14852}
14853
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014854sub xmlSpecChars_R($)
14855{
14856 my $Str = $_[0];
14857 if(not $Str) {
14858 return $Str;
14859 }
14860
14861 $Str=~s/&amp;/&/g;
14862 $Str=~s/&lt;/</g;
14863 $Str=~s/&gt;/>/g;
14864
14865 $Str=~s/&quot;/"/g;
14866 $Str=~s/&#39;/'/g;
14867
14868 return $Str;
14869}
14870
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014871sub black_name($)
14872{
14873 my $Name = $_[0];
14874 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
14875}
14876
14877sub highLight_Signature($)
14878{
14879 my $Signature = $_[0];
14880 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
14881}
14882
14883sub highLight_Signature_Italic_Color($)
14884{
14885 my $Signature = $_[0];
14886 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
14887}
14888
14889sub separate_symbol($)
14890{
14891 my $Symbol = $_[0];
14892 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
14893 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
14894 ($Name, $Spec, $Ver) = ($1, $2, $3);
14895 }
14896 return ($Name, $Spec, $Ver);
14897}
14898
14899sub cut_f_attrs($)
14900{
14901 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
14902 return $2;
14903 }
14904 return "";
14905}
14906
14907sub highLight_Signature_PPos_Italic($$$$$)
14908{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014909 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
14910 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014911 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
14912 my $Return = "";
14913 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
14914 $Return = $2;
14915 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014916 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014917 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014918 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014919 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014920 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014921 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014922 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014923 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014924 }
14925 return $Signature;
14926 }
14927 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
14928 $Begin.=" " if($Begin!~/ \Z/);
14929 $End = cut_f_attrs($Signature);
14930 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014931 my ($Short, $Params) = split_Signature($Signature);
14932 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014933 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014934 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014935 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014936 $Part=~s/\A\s+|\s+\Z//g;
14937 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
14938 if($Part=~/\([\*]+(\w+)\)/i) {
14939 $ParamName = $1;#func-ptr
14940 }
14941 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
14942 $ParamName = $1;
14943 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014944 if(not $ParamName)
14945 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014946 push(@Parts, $Part_Styled);
14947 next;
14948 }
14949 if($ItalicParams and not $TName_Tid{1}{$Part}
14950 and not $TName_Tid{2}{$Part})
14951 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014952 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014953 if($Param_Pos ne ""
14954 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014955 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014956 }
14957 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014958 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014959 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014960 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014961 }
14962 $Part_Styled=~s/,(\w)/, $1/g;
14963 push(@Parts, $Part_Styled);
14964 }
14965 if(@Parts)
14966 {
14967 foreach my $Num (0 .. $#Parts)
14968 {
14969 if($Num==$#Parts)
14970 { # add ")" to the last parameter
14971 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
14972 }
14973 elsif(length($Parts[$Num])<=45) {
14974 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
14975 }
14976 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014977 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014978 }
14979 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014980 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014981 }
14982 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014983 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014984 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014985 $Signature=~s!\[\]![&#160;]!g;
14986 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014987 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
14988 if($SymbolVersion) {
14989 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
14990 }
14991 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014992}
14993
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014994sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014995{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014996 my $Signature = $_[0];
14997 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
14998 {
14999 $Signature=~s/\A\Q$ShortName\E\(//g;
15000 cut_f_attrs($Signature);
15001 $Signature=~s/\)\Z//;
15002 return ($ShortName, $Signature);
15003 }
15004
15005 # error
15006 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015007}
15008
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015009sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015010{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015011 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015012 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015013 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15014 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015015 foreach my $Pos (0 .. length($Params) - 1)
15016 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015017 my $S = substr($Params, $Pos, 1);
15018 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015019 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015020 }
15021 if($S eq "," and
15022 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015023 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015024 if($Comma)
15025 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015026 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015027 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015028 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015029 }
15030 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015031 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015032 }
15033 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015034 if(not $Sp)
15035 { # remove spaces
15036 foreach (@Parts)
15037 {
15038 s/\A //g;
15039 s/ \Z//g;
15040 }
15041 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015042 return @Parts;
15043}
15044
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015045sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015046{
15047 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015048 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015049 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015050 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15051 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015052 $Center+=length($1);
15053 }
15054 foreach my $Pos (0 .. length($Sign)-1)
15055 {
15056 my $S = substr($Sign, $Pos, 1);
15057 if($S eq $Target)
15058 {
15059 if($B{"("}==$B{")"}
15060 and $B{"<"}==$B{">"}) {
15061 return $Center;
15062 }
15063 }
15064 if(defined $B{$S}) {
15065 $B{$S}+=1;
15066 }
15067 $Center+=1;
15068 }
15069 return 0;
15070}
15071
15072sub appendFile($$)
15073{
15074 my ($Path, $Content) = @_;
15075 return if(not $Path);
15076 if(my $Dir = get_dirname($Path)) {
15077 mkpath($Dir);
15078 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015079 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015080 print FILE $Content;
15081 close(FILE);
15082}
15083
15084sub writeFile($$)
15085{
15086 my ($Path, $Content) = @_;
15087 return if(not $Path);
15088 if(my $Dir = get_dirname($Path)) {
15089 mkpath($Dir);
15090 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015091 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015092 print FILE $Content;
15093 close(FILE);
15094}
15095
15096sub readFile($)
15097{
15098 my $Path = $_[0];
15099 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015100 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015101 local $/ = undef;
15102 my $Content = <FILE>;
15103 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015104 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015105 $Content=~s/\r/\n/g;
15106 }
15107 return $Content;
15108}
15109
15110sub get_filename($)
15111{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015112 if(defined $Cache{"get_filename"}{$_[0]}) {
15113 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015114 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015115 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15116 return ($Cache{"get_filename"}{$_[0]}=$1);
15117 }
15118 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015119}
15120
15121sub get_dirname($)
15122{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015123 if(defined $Cache{"get_dirname"}{$_[0]}) {
15124 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015125 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015126 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15127 return ($Cache{"get_dirname"}{$_[0]}=$1);
15128 }
15129 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015130}
15131
15132sub separate_path($) {
15133 return (get_dirname($_[0]), get_filename($_[0]));
15134}
15135
15136sub esc($)
15137{
15138 my $Str = $_[0];
15139 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15140 return $Str;
15141}
15142
15143sub readLineNum($$)
15144{
15145 my ($Path, $Num) = @_;
15146 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015147 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015148 foreach (1 ... $Num) {
15149 <FILE>;
15150 }
15151 my $Line = <FILE>;
15152 close(FILE);
15153 return $Line;
15154}
15155
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015156sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015157{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015158 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015159 return () if(not $Path or not -f $Path);
15160 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015161 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15162 {
15163 foreach my $AttrVal (split(/;/, $1))
15164 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015165 if($AttrVal=~/(.+):(.+)/)
15166 {
15167 my ($Name, $Value) = ($1, $2);
15168 $Attributes{$Name} = $Value;
15169 }
15170 }
15171 }
15172 return \%Attributes;
15173}
15174
15175sub is_abs($) {
15176 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15177}
15178
15179sub get_abs_path($)
15180{ # abs_path() should NOT be called for absolute inputs
15181 # because it can change them
15182 my $Path = $_[0];
15183 if(not is_abs($Path)) {
15184 $Path = abs_path($Path);
15185 }
15186 return $Path;
15187}
15188
15189sub get_OSgroup()
15190{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015191 my $N = $Config{"osname"};
15192 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015193 return "macos";
15194 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015195 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015196 return "bsd";
15197 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015198 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015199 return "beos";
15200 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015201 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015202 return "symbian";
15203 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015204 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015205 return "windows";
15206 }
15207 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015208 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015209 }
15210}
15211
15212sub getGccVersion($)
15213{
15214 my $LibVersion = $_[0];
15215 if($GCC_VERSION{$LibVersion})
15216 { # dump version
15217 return $GCC_VERSION{$LibVersion};
15218 }
15219 elsif($UsedDump{$LibVersion}{"V"})
15220 { # old-version dumps
15221 return "unknown";
15222 }
15223 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15224 if(not $GccVersion) {
15225 return "unknown";
15226 }
15227 return $GccVersion;
15228}
15229
15230sub showArch($)
15231{
15232 my $Arch = $_[0];
15233 if($Arch eq "arm"
15234 or $Arch eq "mips") {
15235 return uc($Arch);
15236 }
15237 return $Arch;
15238}
15239
15240sub getArch($)
15241{
15242 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015243
15244 if($TargetArch) {
15245 return $TargetArch;
15246 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015247 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015248 { # dump version
15249 return $CPU_ARCH{$LibVersion};
15250 }
15251 elsif($UsedDump{$LibVersion}{"V"})
15252 { # old-version dumps
15253 return "unknown";
15254 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015255
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015256 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015257}
15258
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015259sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015260{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015261 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015262
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015263 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015264 if(getArch(1) ne getArch(2)
15265 or getArch(1) eq "unknown"
15266 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015267 { # don't show architecture in the header
15268 $ArchInfo="";
15269 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015270 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015271 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015272 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015273 }
15274 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015275 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015276 }
15277 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015278 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015279 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015280
15281 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15282 {
15283 my $M1 = $UsedDump{1}{"M"};
15284 my $M2 = $UsedDump{2}{"M"};
15285
15286 if($M1 eq $M2)
15287 {
15288 $Title .= " report for the <span style='color:Blue;'>$M1</span> object";
15289 $Title .= " between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions";
15290 }
15291 else
15292 {
15293 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$Descriptor{1}{"Version"}."</span>)";
15294 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$Descriptor{2}{"Version"}."</span>) objects";
15295 }
15296 }
15297 else
15298 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015299 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015300 $Title .= " between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions";
15301 }
15302
15303 $Title .= $ArchInfo;
15304
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015305 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015306 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015307 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015308 $Title = "<h1>".$Title."</h1>\n";
15309 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015310}
15311
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015312sub get_CheckedHeaders($)
15313{
15314 my $LibVersion = $_[0];
15315
15316 my @Headers = ();
15317
15318 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15319 {
15320 my $File = get_filename($Path);
15321 if(not is_target_header($File, $LibVersion)) {
15322 next;
15323 }
15324
15325 if(skipHeader($File, $LibVersion)) {
15326 next;
15327 }
15328
15329 push(@Headers, $Path);
15330 }
15331
15332 return @Headers;
15333}
15334
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015335sub get_SourceInfo()
15336{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015337 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015338
15339 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015340 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015341 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15342 $CheckedHeaders .= "<div class='h_list'>\n";
15343 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 +040015344 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015345 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15346 my $Name = get_filename($Identity);
15347 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15348 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015349 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015350 $CheckedHeaders .= "</div>\n";
15351 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015352 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015353
15354 if(my @Sources = keys(%{$Registered_Sources{1}}))
15355 {
15356 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15357 $CheckedSources .= "<div class='h_list'>\n";
15358 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15359 {
15360 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15361 my $Name = get_filename($Identity);
15362 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15363 $CheckedSources .= $Name.$Comment."<br/>\n";
15364 }
15365 $CheckedSources .= "</div>\n";
15366 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15367 }
15368
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015369 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015370 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015371 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015372 $CheckedLibs .= "<div class='lib_list'>\n";
15373 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15374 {
15375 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15376 $CheckedLibs .= $Library."<br/>\n";
15377 }
15378 $CheckedLibs .= "</div>\n";
15379 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015380 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015381
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015382 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15383}
15384
15385sub get_ObjTitle()
15386{
15387 if(defined $UsedDump{1}{"DWARF"}) {
15388 return "Objects";
15389 }
15390 else {
15391 return ucfirst($SLIB_TYPE)." Libraries";
15392 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015393}
15394
15395sub get_TypeProblems_Count($$$)
15396{
15397 my ($TypeChanges, $TargetPriority, $Level) = @_;
15398 my $Type_Problems_Count = 0;
15399 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15400 {
15401 my %Kinds_Target = ();
15402 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15403 {
15404 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15405 {
15406 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015407 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
15408 next if($Severity ne $TargetPriority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015409 if($Kinds_Target{$Kind}{$Target}) {
15410 next;
15411 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015412
15413 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target})
15414 {
15415 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
15416 { # select a problem with the highest priority
15417 next;
15418 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015419 }
15420 $Kinds_Target{$Kind}{$Target} = 1;
15421 $Type_Problems_Count += 1;
15422 }
15423 }
15424 }
15425 return $Type_Problems_Count;
15426}
15427
15428sub get_Summary($)
15429{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015430 my $Level = $_[0];
15431 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015432 $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 +040015433 %{$RESULT{$Level}} = (
15434 "Problems"=>0,
15435 "Warnings"=>0,
15436 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015437 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015438 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015439 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015440 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015441 {
15442 if(not defined $CompatRules{$Level}{$Kind})
15443 { # unknown rule
15444 if(not $UnknownRules{$Level}{$Kind})
15445 { # only one warning
15446 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15447 $UnknownRules{$Level}{$Kind}=1;
15448 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015449 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015450 }
15451 }
15452 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015453 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15454 {
15455 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15456 {
15457 if(not defined $CompatRules{$Level}{$Kind})
15458 { # unknown rule
15459 if(not $UnknownRules{$Level}{$Kind})
15460 { # only one warning
15461 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15462 $UnknownRules{$Level}{$Kind}=1;
15463 }
15464 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15465 }
15466 }
15467 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015468 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015469 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015470 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015471 {
15472 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15473 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015474 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015475 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015476 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015477 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015478 $Added += 1;
15479 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015480 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015481 {
15482 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015483 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015484 }
15485 else
15486 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015487 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015488 $I_Other += 1;
15489 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015490 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015491 $I_Problems_High += 1;
15492 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015493 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015494 $I_Problems_Medium += 1;
15495 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015496 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015497 $I_Problems_Low += 1;
15498 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015499 if(($Severity ne "Low" or $StrictCompat)
15500 and $Severity ne "Safe") {
15501 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015502 }
15503 }
15504 }
15505 }
15506 }
15507 }
15508 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015509 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015510 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015511 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015512 {
15513 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15514 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015515 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015516 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015517 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15518 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015519 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015520 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15521
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015522 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015523 { # select a problem with the highest priority
15524 next;
15525 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015526
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015527 if(($Severity ne "Low" or $StrictCompat)
15528 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015529 {
15530 if(defined $TotalAffected{$Level}{$Interface})
15531 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015532 if($Severity_Val{$Severity}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15533 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015534 }
15535 }
15536 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015537 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015538 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015539 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015540
15541 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15542
15543 if($MaxSeverity)
15544 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015545 if($Severity_Val{$Severity}>$Severity_Val{$MaxSeverity}) {
15546 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015547 }
15548 }
15549 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015550 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015551 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015552 }
15553 }
15554 }
15555 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015556
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015557 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15558 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15559 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15560 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015561
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015562 %TypeChanges = (); # free memory
15563
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015564 # changed and removed public symbols
15565 my $SCount = keys(%{$CheckedSymbols{$Level}});
15566 if($ExtendedCheck)
15567 { # don't count external_func_0 for constants
15568 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015569 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015570 if($SCount)
15571 {
15572 my %Weight = (
15573 "High" => 100,
15574 "Medium" => 50,
15575 "Low" => 25
15576 );
15577 foreach (keys(%{$TotalAffected{$Level}})) {
15578 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015579 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015580 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015581 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015582 else {
15583 $RESULT{$Level}{"Affected"} = 0;
15584 }
15585
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015586 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15587 if($RESULT{$Level}{"Affected"}>=100) {
15588 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015589 }
15590
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015591 $RESULT{$Level}{"Problems"} += $Removed;
15592 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015593 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015594 if($StrictCompat) {
15595 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15596 }
15597 else {
15598 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15599 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015600
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015601 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015602 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015603 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015604 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015605 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015606 if($Severity eq "Safe")
15607 {
15608 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015609 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015610 elsif($Severity eq "Low")
15611 {
15612 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015613 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015614 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015615 }
15616
15617 if($C_Problems_Low)
15618 {
15619 if($StrictCompat) {
15620 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15621 }
15622 else {
15623 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015624 }
15625 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015626 if($RESULT{$Level}{"Problems"}
15627 and $RESULT{$Level}{"Affected"}) {
15628 $RESULT{$Level}{"Verdict"} = "incompatible";
15629 }
15630 else {
15631 $RESULT{$Level}{"Verdict"} = "compatible";
15632 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015633
15634 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15635 if(not $TotalTypes)
15636 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015637 $TotalTypes = keys(%{$TName_Tid{1}});
15638 }
15639
15640 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15641 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15642
15643 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15644
15645 if($ReportFormat eq "xml")
15646 { # XML
15647 # test info
15648 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15649 $TestInfo .= " <version1>\n";
15650 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015651 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015652 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15653 $TestInfo .= " </version1>\n";
15654
15655 $TestInfo .= " <version2>\n";
15656 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015657 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015658 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15659 $TestInfo .= " </version2>\n";
15660 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15661
15662 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015663 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015664 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015665 $TestResults .= " <headers>\n";
15666 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15667 {
15668 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15669 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15670 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15671 }
15672 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015673 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015674
15675 if(my @Sources = keys(%{$Registered_Sources{1}}))
15676 {
15677 $TestResults .= " <sources>\n";
15678 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15679 {
15680 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15681 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15682 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15683 }
15684 $TestResults .= " </sources>\n";
15685 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015686
15687 $TestResults .= " <libs>\n";
15688 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15689 {
15690 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15691 $TestResults .= " <name>$Library</name>\n";
15692 }
15693 $TestResults .= " </libs>\n";
15694
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015695 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015696 $TestResults .= " <types>".$TotalTypes."</types>\n";
15697
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015698 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15699 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015700 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15701
15702 # problem summary
15703 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15704 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15705
15706 $Problem_Summary .= " <problems_with_types>\n";
15707 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15708 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15709 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15710 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15711 $Problem_Summary .= " </problems_with_types>\n";
15712
15713 $Problem_Summary .= " <problems_with_symbols>\n";
15714 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15715 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15716 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015717 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015718 $Problem_Summary .= " </problems_with_symbols>\n";
15719
15720 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015721 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015722 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015723
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015724 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15725
15726 return ($TestInfo.$TestResults.$Problem_Summary, "");
15727 }
15728 else
15729 { # HTML
15730 # test info
15731 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015732 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015733 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetTitle</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015734
15735 my (@VInf1, @VInf2, $AddTestInfo) = ();
15736 if($Arch1 ne "unknown"
15737 and $Arch2 ne "unknown")
15738 { # CPU arch
15739 if($Arch1 eq $Arch2)
15740 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015741 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015742 }
15743 else
15744 { # go to the version number
15745 push(@VInf1, showArch($Arch1));
15746 push(@VInf2, showArch($Arch2));
15747 }
15748 }
15749 if($GccV1 ne "unknown"
15750 and $GccV2 ne "unknown"
15751 and $OStarget ne "windows")
15752 { # GCC version
15753 if($GccV1 eq $GccV2)
15754 { # go to the separate section
15755 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15756 }
15757 else
15758 { # go to the version number
15759 push(@VInf1, "gcc ".$GccV1);
15760 push(@VInf2, "gcc ".$GccV2);
15761 }
15762 }
15763 # show long version names with GCC version and CPU architecture name (if different)
15764 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
15765 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
15766 $TestInfo .= $AddTestInfo;
15767 #if($COMMON_LANGUAGE{1}) {
15768 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
15769 #}
15770 if($ExtendedCheck) {
15771 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
15772 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015773 if($JoinReport)
15774 {
15775 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015776 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015777 }
15778 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015779 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015780 }
15781 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015782 $TestInfo .= "</table>\n";
15783
15784 # test results
15785 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015786 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015787
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030015788 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015789 {
15790 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
15791 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
15792 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015793
15794 if(my @Sources = keys(%{$Registered_Sources{1}}))
15795 {
15796 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
15797 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
15798 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015799
15800 if(not $ExtendedCheck)
15801 {
15802 my $Libs_Link = "0";
15803 $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 +040015804 $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 +040015805 }
15806
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015807 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015808
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015809 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015810 if($JoinReport) {
15811 $META_DATA = "kind:".lc($Level).";".$META_DATA;
15812 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015813 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015814 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015815 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
15816 }
15817 else {
15818 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
15819 }
15820 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015821 $TestResults .= "</table>\n";
15822
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015823 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015824 # problem summary
15825 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015826 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015827 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
15828
15829 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015830 if($Added>0)
15831 {
15832 if($JoinReport) {
15833 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
15834 }
15835 else {
15836 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
15837 }
15838 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015839 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015840 $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 +040015841
15842 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015843 if($Removed>0)
15844 {
15845 if($JoinReport) {
15846 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
15847 }
15848 else {
15849 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
15850 }
15851 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015852 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015853 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
15854 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015855
15856 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015857 $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 +040015858 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015859 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
15860 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015861
15862 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015863 $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 +040015864 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015865 $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 +040015866
15867 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015868 $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 +040015869 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015870 $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 +040015871
15872 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015873 $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 +040015874 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015875 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
15876 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015877
15878 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015879 $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 +040015880 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015881 $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 +040015882
15883 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015884 $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 +040015885 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015886 $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 +040015887
15888 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015889 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
15890 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015891 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015892 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015893 $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 +040015894
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015895 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015896 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015897 {
15898 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015899 $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 +040015900 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015901
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015902 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015903 {
15904 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015905 $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 +040015906 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015907
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015908 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015909 {
15910 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
15911 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
15912 }
15913
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015914 $META_DATA .= "tool_version:$TOOL_VERSION";
15915 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015916 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015917 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
15918 }
15919}
15920
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015921sub getStyle($$$)
15922{
15923 my ($Subj, $Act, $Num) = @_;
15924 my %Style = (
15925 "A"=>"new",
15926 "R"=>"failed",
15927 "S"=>"passed",
15928 "L"=>"warning",
15929 "M"=>"failed",
15930 "H"=>"failed"
15931 );
15932 if($Num>0) {
15933 return " class='".$Style{$Act}."'";
15934 }
15935 return "";
15936}
15937
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015938sub show_number($)
15939{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015940 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015941 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015942 my $Num = cut_off_number($_[0], 2, 0);
15943 if($Num eq "0")
15944 {
15945 foreach my $P (3 .. 7)
15946 {
15947 $Num = cut_off_number($_[0], $P, 1);
15948 if($Num ne "0") {
15949 last;
15950 }
15951 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015952 }
15953 if($Num eq "0") {
15954 $Num = $_[0];
15955 }
15956 return $Num;
15957 }
15958 return $_[0];
15959}
15960
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015961sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015962{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015963 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015964 if($num!~/\./)
15965 {
15966 $num .= ".";
15967 foreach (1 .. $digs_to_cut-1) {
15968 $num .= "0";
15969 }
15970 }
15971 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
15972 {
15973 foreach (1 .. $digs_to_cut - 1 - length($1)) {
15974 $num .= "0";
15975 }
15976 }
15977 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
15978 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
15979 }
15980 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015981 if($z) {
15982 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
15983 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015984 return $num;
15985}
15986
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015987sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015988{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015989 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015990 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015991
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015992 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015993 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
15994 {
15995 my $Header = $Constants{1}{$Constant}{"Header"};
15996 if(not $Header)
15997 { # added
15998 $Header = $Constants{2}{$Constant}{"Header"}
15999 }
16000
16001 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16002 {
16003 if(not defined $CompatRules{$Level}{$Kind}) {
16004 next;
16005 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016006 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016007 next;
16008 }
16009 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16010 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016011 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016012
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016013 if($ReportFormat eq "xml")
16014 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016015 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016016 {
16017 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016018 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016019 {
16020 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016021 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16022 {
16023 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16024 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16025 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016026
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016027 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16028 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16029 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016030 if($Overcome) {
16031 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16032 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016033 $CHANGED_CONSTANTS .= " </problem>\n";
16034 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016035 $CHANGED_CONSTANTS .= " </constant>\n";
16036 }
16037 $CHANGED_CONSTANTS .= " </header>\n";
16038 }
16039 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16040 }
16041 else
16042 { # HTML
16043 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016044 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016045 {
16046 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016047 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016048 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016049 my $Report = "";
16050
16051 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16052 {
16053 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16054 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16055 $Report .= "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16056 $Number += 1;
16057 }
16058 if($Report)
16059 {
16060 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n";
16061 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16062 $Report = insertIDs($Report);
16063 }
16064 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016065 }
16066 $CHANGED_CONSTANTS .= "<br/>\n";
16067 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016068 if($CHANGED_CONSTANTS)
16069 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016070 my $Title = "Problems with Constants, $TargetSeverity Severity";
16071 if($TargetSeverity eq "Safe")
16072 { # Safe Changes
16073 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016074 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016075 $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 +040016076 }
16077 }
16078 return $CHANGED_CONSTANTS;
16079}
16080
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016081sub getTitle($$$)
16082{
16083 my ($Header, $Library, $NameSpace) = @_;
16084 my $Title = "";
16085 if($Library and $Library!~/\.\w+\Z/) {
16086 $Library .= " (.$LIB_EXT)";
16087 }
16088 if($Header and $Library)
16089 {
16090 $Title .= "<span class='h_name'>$Header</span>";
16091 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16092 }
16093 elsif($Library) {
16094 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16095 }
16096 elsif($Header) {
16097 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16098 }
16099 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016100 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016101 }
16102 return $Title;
16103}
16104
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016105sub get_Report_Added($)
16106{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016107 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016108 my $ADDED_INTERFACES = "";
16109 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016110 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016111 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016112 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016113 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016114 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016115 {
16116 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16117 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016118 if($Level eq "Source" and $ReportFormat eq "html")
16119 { # do not show library name in HTML report
16120 $DyLib = "";
16121 }
16122 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016123 }
16124 }
16125 }
16126 if($ReportFormat eq "xml")
16127 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016128 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016129 {
16130 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016131 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016132 {
16133 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016134 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016135 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16136 }
16137 $ADDED_INTERFACES .= " </library>\n";
16138 }
16139 $ADDED_INTERFACES .= " </header>\n";
16140 }
16141 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16142 }
16143 else
16144 { # HTML
16145 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016146 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016147 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016148 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016149 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016150 my %NameSpaceSymbols = ();
16151 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016152 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016153 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016154 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016155 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016156 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16157 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016158 foreach my $Interface (@SortedInterfaces)
16159 {
16160 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016161 my $Signature = get_Signature($Interface, 2);
16162 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016163 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016164 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016165 if($Interface=~/\A(_Z|\?)/)
16166 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016167 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016168 $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 +040016169 }
16170 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016171 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016172 }
16173 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016174 else
16175 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016176 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016177 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016178 }
16179 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016180 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016181 }
16182 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016183 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016184 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016185 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016186 }
16187 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016188 if($ADDED_INTERFACES)
16189 {
16190 my $Anchor = "<a name='Added'></a>";
16191 if($JoinReport) {
16192 $Anchor = "<a name='".$Level."_Added'></a>";
16193 }
16194 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016195 }
16196 }
16197 return $ADDED_INTERFACES;
16198}
16199
16200sub get_Report_Removed($)
16201{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016202 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016203 my $REMOVED_INTERFACES = "";
16204 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016205 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016206 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016207 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016208 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016209 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016210 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016211 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16212 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016213 if($Level eq "Source" and $ReportFormat eq "html")
16214 { # do not show library name in HTML report
16215 $DyLib = "";
16216 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016217 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016218 }
16219 }
16220 }
16221 if($ReportFormat eq "xml")
16222 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016223 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016224 {
16225 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016226 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016227 {
16228 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016229 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16230 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016231 }
16232 $REMOVED_INTERFACES .= " </library>\n";
16233 }
16234 $REMOVED_INTERFACES .= " </header>\n";
16235 }
16236 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16237 }
16238 else
16239 { # HTML
16240 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016241 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016242 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016243 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016244 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016245 my %NameSpaceSymbols = ();
16246 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016247 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016248 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016249 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016250 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016251 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16252 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016253 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016254 {
16255 $Removed_Number += 1;
16256 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016257 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016258 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016259 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016260 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016261 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016262 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016263 if($Signature) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016264 $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 +040016265 }
16266 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016267 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016268 }
16269 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016270 else
16271 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016272 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016273 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016274 }
16275 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016276 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016277 }
16278 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016279 }
16280 }
16281 $REMOVED_INTERFACES .= "<br/>\n";
16282 }
16283 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016284 if($REMOVED_INTERFACES)
16285 {
16286 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16287 if($JoinReport) {
16288 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16289 }
16290 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016291 }
16292 }
16293 return $REMOVED_INTERFACES;
16294}
16295
16296sub getXmlParams($$)
16297{
16298 my ($Content, $Problem) = @_;
16299 return "" if(not $Content or not $Problem);
16300 my %XMLparams = ();
16301 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16302 {
16303 my $Macro = "\@".lc($Attr);
16304 if($Content=~/\Q$Macro\E/) {
16305 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16306 }
16307 }
16308 my @PString = ();
16309 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016310 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016311 }
16312 if(@PString) {
16313 return " ".join(" ", @PString);
16314 }
16315 else {
16316 return "";
16317 }
16318}
16319
16320sub addMarkup($)
16321{
16322 my $Content = $_[0];
16323 # auto-markup
16324 $Content=~s/\n[ ]*//; # spaces
16325 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16326 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016327 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016328 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16329 if($Content=~/\ANOTE:/)
16330 { # notes
16331 $Content=~s!(NOTE):!<b>$1</b>:!g;
16332 }
16333 else {
16334 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16335 }
16336 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16337 my @Keywords = (
16338 "void",
16339 "const",
16340 "static",
16341 "restrict",
16342 "volatile",
16343 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016344 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016345 );
16346 my $MKeys = join("|", @Keywords);
16347 foreach (@Keywords) {
16348 $MKeys .= "|non-".$_;
16349 }
16350 $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 +040016351
16352 # Markdown
16353 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16354 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016355 return $Content;
16356}
16357
16358sub applyMacroses($$$$)
16359{
16360 my ($Level, $Kind, $Content, $Problem) = @_;
16361 return "" if(not $Content or not $Problem);
16362 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16363 $Content = addMarkup($Content);
16364 # macros
16365 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16366 {
16367 my $Macro = "\@".lc($Attr);
16368 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016369 if(not defined $Value
16370 or $Value eq "") {
16371 next;
16372 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016373 if($Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016374 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016375 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
16376 $Value=~s/\s\w+(\)|,)/$1/g; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016377 $Value = black_name($Value);
16378 }
16379 elsif($Value=~/\s/) {
16380 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16381 }
16382 elsif($Value=~/\A\d+\Z/
16383 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16384 { # bits to bytes
16385 if($Value % $BYTE_SIZE)
16386 { # bits
16387 if($Value==1) {
16388 $Value = "<b>".$Value."</b> bit";
16389 }
16390 else {
16391 $Value = "<b>".$Value."</b> bits";
16392 }
16393 }
16394 else
16395 { # bytes
16396 $Value /= $BYTE_SIZE;
16397 if($Value==1) {
16398 $Value = "<b>".$Value."</b> byte";
16399 }
16400 else {
16401 $Value = "<b>".$Value."</b> bytes";
16402 }
16403 }
16404 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016405 else
16406 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016407 $Value = "<b>".htmlSpecChars($Value)."</b>";
16408 }
16409 $Content=~s/\Q$Macro\E/$Value/g;
16410 }
16411
16412 if($Content=~/(\A|[^\@\w])\@\w/)
16413 {
16414 if(not $IncompleteRules{$Level}{$Kind})
16415 { # only one warning
16416 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16417 $IncompleteRules{$Level}{$Kind} = 1;
16418 }
16419 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016420 return $Content;
16421}
16422
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016423sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016424{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016425 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016426 my $INTERFACE_PROBLEMS = "";
16427 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016428
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016429 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016430 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016431 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16432 if($SV and defined $CompatProblems{$Level}{$SN}) {
16433 next;
16434 }
16435 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016436 {
16437 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016438 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016439 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016440 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16441 my $DyLib = $Symbol_Library{1}{$Symbol};
16442 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016443 { # Symbol with Version
16444 $DyLib = $Symbol_Library{1}{$VSym};
16445 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016446 if(not $DyLib)
16447 { # const global data
16448 $DyLib = "";
16449 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016450 if($Level eq "Source" and $ReportFormat eq "html")
16451 { # do not show library name in HTML report
16452 $DyLib = "";
16453 }
16454 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16455 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016456 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016457 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16458 if($Severity ne $TargetSeverity) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016459 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016460 }
16461 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016462 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16463 {
16464 delete($SymbolChanges{$Symbol}{$Kind});
16465 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016466 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016467 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016468 }
16469 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016470 if(not keys(%{$SymbolChanges{$Symbol}})) {
16471 delete($SymbolChanges{$Symbol});
16472 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016473 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016474
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016475 if($ReportFormat eq "xml")
16476 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016477 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016478 {
16479 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016480 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016481 {
16482 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016483 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16484 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016485 {
16486 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16487 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16488 {
16489 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16490 {
16491 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016492 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016493
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016494 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16495 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16496 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16497 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16498 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016499 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16500 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16501 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016502 $INTERFACE_PROBLEMS .= " </problem>\n";
16503 }
16504 }
16505 $INTERFACE_PROBLEMS .= " </symbol>\n";
16506 }
16507 $INTERFACE_PROBLEMS .= " </library>\n";
16508 }
16509 $INTERFACE_PROBLEMS .= " </header>\n";
16510 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016511 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016512 }
16513 else
16514 { # HTML
16515 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016516 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016517 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016518 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016519 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016520 my (%NameSpaceSymbols, %NewSignature) = ();
16521 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016522 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016523 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016524 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016525 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016526 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016527 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016528 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016529 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016530 my $Signature = get_Signature($Symbol, 1);
16531 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016532 my $ProblemNum = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016533 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016534 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016535 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016536 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016537 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016538 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016539 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016540 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016541 }
16542 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16543 {
16544 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016545 $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 +040016546 $ProblemNum += 1;
16547 $ProblemsNum += 1;
16548 }
16549 }
16550 }
16551 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016552 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016553 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016554 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016555 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016556 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016557 }
16558 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016559 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016560 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016561 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16562 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16563 if($NewSignature{$Symbol})
16564 { # argument list changed to
16565 $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 +040016566 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016567 if($Symbol=~/\A(_Z|\?)/) {
16568 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16569 }
16570 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n";
16571 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016572 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016573 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016574 }
16575 }
16576 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016577 $INTERFACE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016578 }
16579 }
16580 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016581
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016582 if($INTERFACE_PROBLEMS)
16583 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016584 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16585 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16586 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016587 { # Safe Changes
16588 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016589 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016590 $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 +040016591 }
16592 }
16593 return $INTERFACE_PROBLEMS;
16594}
16595
16596sub get_Report_TypeProblems($$)
16597{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016598 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016599 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016600 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016601
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016602 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016603 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016604 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016605 {
16606 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16607 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016608 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016609 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016610 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016611 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016612 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016613
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016614 if($Severity eq "Safe"
16615 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016616 next;
16617 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016618
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016619 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target})
16620 {
16621 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
16622 { # select a problem with the highest priority
16623 next;
16624 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016625 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016626
16627 $TypeChanges{$TypeName}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016628 }
16629 }
16630 }
16631 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016632
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016633 my %Kinds_Locations = ();
16634 foreach my $TypeName (keys(%TypeChanges))
16635 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016636 my %Kind_Target = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016637 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16638 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016639 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016640 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016641 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016642 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016643 { # other priority
16644 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16645 next;
16646 }
16647 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16648 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016649 if($Kind_Target{$Kind}{$Target})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016650 { # duplicate target
16651 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16652 next;
16653 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016654 $Kind_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016655 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016656 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016657 }
16658 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16659 delete($TypeChanges{$TypeName}{$Kind});
16660 }
16661 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016662 if(not keys(%{$TypeChanges{$TypeName}})) {
16663 delete($TypeChanges{$TypeName});
16664 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016665 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016666
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016667 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 +040016668 if($ReportFormat eq "xml")
16669 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016670 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016671 {
16672 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016673 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016674 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016675 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016676 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16677 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016678 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016679 {
16680 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16681 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16682 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16683 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16684 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16685 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016686 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16687 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16688 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016689 $TYPE_PROBLEMS .= " </problem>\n";
16690 }
16691 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016692 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016693 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016694 $TYPE_PROBLEMS .= showVTables($TypeName);
16695 }
16696 $TYPE_PROBLEMS .= " </type>\n";
16697 }
16698 $TYPE_PROBLEMS .= " </header>\n";
16699 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016700 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016701 }
16702 else
16703 { # HTML
16704 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016705 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016706 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016707 my (%NameSpace_Type) = ();
16708 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016709 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016710 }
16711 foreach my $NameSpace (sort keys(%NameSpace_Type))
16712 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016713 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016714 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 +040016715 foreach my $TypeName (@SortedTypes)
16716 {
16717 my $ProblemNum = 1;
16718 my $TYPE_REPORT = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016719
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016720 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16721 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016722 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016723 {
16724 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16725 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16726 {
16727 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
16728 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16729 $ProblemNum += 1;
16730 $ProblemsNum += 1;
16731 }
16732 }
16733 }
16734 $ProblemNum -= 1;
16735 if($TYPE_REPORT)
16736 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016737 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016738 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016739 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016740 $ShowVTables = showVTables($TypeName);
16741 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016742
16743 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016744 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
16745 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
16746 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
16747 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016748 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016749 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016750 }
16751 }
16752 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016753 $TYPE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016754 }
16755 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016756
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016757 if($TYPE_PROBLEMS)
16758 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016759 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
16760 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016761 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016762 { # Safe Changes
16763 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016764 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016765 $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 +040016766 }
16767 }
16768 return $TYPE_PROBLEMS;
16769}
16770
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016771sub show_Type($$$)
16772{
16773 my ($Name, $Html, $LibVersion) = @_;
16774 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
16775 $TType = lc($TType);
16776 if($TType=~/struct|union|enum/) {
16777 $Name=~s/\A\Q$TType\E //g;
16778 }
16779 if($Html) {
16780 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
16781 }
16782 else {
16783 $Name = $TType." ".$Name;
16784 }
16785 return $Name;
16786}
16787
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016788sub get_Anchor($$$)
16789{
16790 my ($Kind, $Level, $Severity) = @_;
16791 if($JoinReport)
16792 {
16793 if($Severity eq "Safe") {
16794 return "Other_".$Level."_Changes_In_".$Kind."s";
16795 }
16796 else {
16797 return $Kind."_".$Level."_Problems_".$Severity;
16798 }
16799 }
16800 else
16801 {
16802 if($Severity eq "Safe") {
16803 return "Other_Changes_In_".$Kind."s";
16804 }
16805 else {
16806 return $Kind."_Problems_".$Severity;
16807 }
16808 }
16809}
16810
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016811sub showVTables($)
16812{
16813 my $TypeName = $_[0];
16814 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016815 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016816 if(defined $Type1{"VTable"}
16817 and keys(%{$Type1{"VTable"}}))
16818 {
16819 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016820 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016821 if(defined $Type2{"VTable"}
16822 and keys(%{$Type2{"VTable"}}))
16823 {
16824 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
16825 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016826 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016827 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016828 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
16829 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016830 }
16831 my $VTABLES = "";
16832 if($ReportFormat eq "xml")
16833 { # XML
16834 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016835 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016836 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016837 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016838 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
16839 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016840 $VTABLES .= " </entry>\n";
16841 }
16842 $VTABLES .= " </vtable>\n\n";
16843 }
16844 else
16845 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016846 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030016847 $VTABLES .= "<tr><th>Offset</th>";
16848 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016849 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016850 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016851 {
16852 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016853 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016854 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016855 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016856 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016857 $Color1 = " class='failed'";
16858 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016859 }
16860 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016861 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016862 }
16863 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016864 $VTABLES .= "<tr><th>".$Index."</th>\n";
16865 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
16866 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016867 }
16868 $VTABLES .= "</table><br/>\n";
16869 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016870 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016871 }
16872 return $VTABLES;
16873 }
16874 }
16875 return "";
16876}
16877
16878sub simpleVEntry($)
16879{
16880 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016881 if(not defined $VEntry
16882 or $VEntry eq "") {
16883 return "";
16884 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030016885
16886 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016887 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
16888 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
16889 if($VEntry=~/\A_ZThn.+\Z/) {
16890 $VEntry = "non-virtual thunk";
16891 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016892 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016893 # support for old GCC versions
16894 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
16895 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
16896 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016897 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
16898 return $VEntry;
16899}
16900
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016901sub adjustParamPos($$$)
16902{
16903 my ($Pos, $Symbol, $LibVersion) = @_;
16904 if(defined $CompleteSignature{$LibVersion}{$Symbol})
16905 {
16906 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
16907 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
16908 {
16909 return $Pos-1;
16910 }
16911
16912 return $Pos;
16913 }
16914
16915 return undef;
16916}
16917
16918sub getParamPos($$$)
16919{
16920 my ($Name, $Symbol, $LibVersion) = @_;
16921
16922 if(defined $CompleteSignature{$LibVersion}{$Symbol}
16923 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
16924 {
16925 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
16926 foreach (keys(%{$Info->{"Param"}}))
16927 {
16928 if($Info->{"Param"}{$_}{"name"} eq $Name)
16929 {
16930 return $_;
16931 }
16932 }
16933 }
16934
16935 return undef;
16936}
16937
16938sub getParamName($)
16939{
16940 my $Loc = $_[0];
16941 $Loc=~s/\->.*//g;
16942 return $Loc;
16943}
16944
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016945sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016946{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016947 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016948 my $LIMIT = 10;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016949
16950 if(defined $AffectLimit)
16951 {
16952 $LIMIT = $AffectLimit;
16953 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016954
16955 my %SymSel = ();
16956 my %SymLocKind = ();
16957
16958 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016959 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016960 if(index($Symbol, "_Z")==0
16961 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016962 { # duplicated problems for C2 constructors, D2 and D0 destructors
16963 next;
16964 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016965
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016966 foreach my $Kind (sort keys(%{$Kinds_Locations}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016967 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016968 if(not defined $CompatProblems{$Level}{$Symbol}
16969 or not defined $CompatProblems{$Level}{$Symbol}{$Kind}) {
16970 next;
16971 }
16972
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016973 foreach my $Loc (sort keys(%{$Kinds_Locations->{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016974 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016975 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016976 next;
16977 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016978
16979 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16980 if($Level eq "Source")
16981 { # remove symbol version
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016982 $Symbol = $SN;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016983 }
16984
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016985 if($SV and defined $CompatProblems{$Level}{$SN}
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016986 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016987 { # duplicated problems for versioned symbols
16988 next;
16989 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016990
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016991 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016992 if($Type_Name ne $Target_TypeName) {
16993 next;
16994 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016995
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030016996 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016997 }
16998 }
16999 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017000
17001 foreach my $Symbol (sort keys(%SymLocKind))
17002 {
17003 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17004 {
17005 foreach my $Kind (keys(%{$SymLocKind{$Symbol}{$Loc}}))
17006 {
17007 $SymSel{$Symbol}{"Loc"} = $Loc;
17008 $SymSel{$Symbol}{"Kind"} = $Kind;
17009
17010 last LOOP;
17011 }
17012 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017013 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017014
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017015 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017016 my $Num = 0;
17017
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017018 if($ReportFormat eq "xml")
17019 { # XML
17020 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017021
17022 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017023 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017024 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017025 my $PName = getParamName($Loc);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017026 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017027
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017028 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017029 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017030 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017031 $Target .= " param=\"$PName\"";
17032 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017033 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017034 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017035 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017036 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017037 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017038 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017039 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017040
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017041 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017042 $Target .= " field=\"$1\"";
17043 }
17044
17045 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017046 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017047 $Affected .= " </symbol>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017048
17049 if($Num>$LIMIT) {
17050 last LOOP;
17051 }
17052
17053 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017054 }
17055 $Affected .= " </affected>\n";
17056 }
17057 else
17058 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017059 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017060 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017061 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $SymSel{$Symbol}{"Loc"});
17062 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017063 my $PName = getParamName($SymSel{$Symbol}{"Loc"});
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017064 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17065
17066 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>";
17067 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
17068
17069 if($Num>$LIMIT) {
17070 last;
17071 }
17072
17073 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017074 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017075
17076 if(keys(%SymSel)>$LIMIT) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017077 $Affected .= " ...<br/>"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017078 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017079
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017080 $Affected = "<div class='affected'>".$Affected."</div>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017081 if($Affected)
17082 {
17083 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017084 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".keys(%SymSel).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017085 }
17086 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017087
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017088 return $Affected;
17089}
17090
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017091sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017092{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017093 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017094 if($L2=~/\A(retval|this)\b/
17095 and $L1!~/\A(retval|this)\b/)
17096 {
17097 if($L1!~/\-\>/) {
17098 return 1;
17099 }
17100 elsif($L2=~/\-\>/) {
17101 return 1;
17102 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017103 }
17104 return 0;
17105}
17106
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017107sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017108{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017109 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017110
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017111 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017112
17113 my $Location_I = $Location;
17114 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17115
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017116 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017117
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017118 if($Kind eq "Overridden_Virtual_Method"
17119 or $Kind eq "Overridden_Virtual_Method_B") {
17120 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17121 }
17122 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17123 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017124 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17125
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017126 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17127 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017128 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17129 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17130
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017131 if($ClassName eq $Problem{"Type_Name"}) {
17132 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17133 }
17134 else {
17135 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17136 }
17137 }
17138 else
17139 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017140 my $TypeID = undef;
17141
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017142 if($Location=~/retval/)
17143 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017144 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017145 push(@Sentence, "Field \'".$Location."\' in return value");
17146 }
17147 else {
17148 push(@Sentence, "Return value");
17149 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017150
17151 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017152 }
17153 elsif($Location=~/this/)
17154 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017155 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017156 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17157 }
17158 else {
17159 push(@Sentence, "\'this\' pointer");
17160 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017161
17162 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017163 }
17164 else
17165 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017166
17167 my $PName = getParamName($Location);
17168 my $PPos = getParamPos($PName, $Symbol, 1);
17169
17170 if(index($Location, "->")!=-1) {
17171 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017172 }
17173 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017174 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017175 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017176 if($PName) {
17177 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017178 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017179
17180 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17181 }
17182
17183 if($Location!~/this/)
17184 {
17185 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017186 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017187 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017188 push(@Sentence, "(pointer)");
17189 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017190 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017191 push(@Sentence, "(reference)");
17192 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017193 }
17194 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017195
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017196 if($Location eq "this") {
17197 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17198 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017199 else
17200 {
17201 my $Location_T = $Location;
17202 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17203
17204 my $TypeID_Problem = $TypeID;
17205 if($Location_T) {
17206 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17207 }
17208
17209 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17210 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17211 }
17212 else {
17213 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17214 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017215 }
17216 }
17217 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017218 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017219 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 +040017220 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017221
17222 my $Sent = join(" ", @Sentence);
17223
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017224 $Sent=~s/->/./g;
17225
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017226 if($ReportFormat eq "xml")
17227 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017228 $Sent=~s/'//g;
17229 }
17230
17231 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017232}
17233
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017234sub getFieldType($$$)
17235{
17236 my ($Location, $TypeId, $LibVersion) = @_;
17237
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017238 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017239
17240 foreach my $Name (@Fields)
17241 {
17242 my %Info = get_BaseType($TypeId, $LibVersion);
17243
17244 foreach my $Pos (keys(%{$Info{"Memb"}}))
17245 {
17246 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17247 {
17248 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17249 last;
17250 }
17251 }
17252 }
17253
17254 return $TypeId;
17255}
17256
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017257sub get_XmlSign($$)
17258{
17259 my ($Symbol, $LibVersion) = @_;
17260 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17261 my $Report = "";
17262 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17263 {
17264 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017265 my $Type = $Info->{"Param"}{$Pos}{"type"};
17266 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017267 foreach my $Typedef (keys(%ChangedTypedef))
17268 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017269 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17270 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17271 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017272 }
17273 $Report .= " <param pos=\"$Pos\">\n";
17274 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017275 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017276 $Report .= " </param>\n";
17277 }
17278 if(my $Return = $Info->{"Return"})
17279 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017280 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017281 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017282 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017283 $Report .= " </retval>\n";
17284 }
17285 return $Report;
17286}
17287
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017288sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017289{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017290 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017291 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017292 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017293 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017294 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17295 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017296 next;
17297 }
17298 $Report .= " <symbol name=\"$Symbol\">\n";
17299 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017300 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017301 {
17302 if(defined $CompleteSignature{1}{$Symbol}
17303 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17304 {
17305 $P1 = get_XmlSign($Symbol, 1);
17306 $S1 = get_Signature($Symbol, 1);
17307 }
17308 elsif($Symbol=~/\A(_Z|\?)/) {
17309 $S1 = $tr_name{$Symbol};
17310 }
17311 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017312 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017313 {
17314 if(defined $CompleteSignature{2}{$Symbol}
17315 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17316 {
17317 $P2 = get_XmlSign($Symbol, 2);
17318 $S2 = get_Signature($Symbol, 2);
17319 }
17320 elsif($Symbol=~/\A(_Z|\?)/) {
17321 $S2 = $tr_name{$Symbol};
17322 }
17323 }
17324 if($S1)
17325 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017326 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017327 $Report .= $P1;
17328 $Report .= " </old>\n";
17329 }
17330 if($S2 and $S2 ne $S1)
17331 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017332 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017333 $Report .= $P2;
17334 $Report .= " </new>\n";
17335 }
17336 $Report .= " </symbol>\n";
17337 }
17338 $Report .= "</symbols_info>\n";
17339 return $Report;
17340}
17341
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017342sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017343{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017344 my ($Level, $Report) = @_;
17345 if($ReportFormat eq "xml") {
17346 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017347 }
17348 if($StdOut)
17349 { # --stdout option
17350 print STDOUT $Report;
17351 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017352 else
17353 {
17354 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017355 mkpath(get_dirname($RPath));
17356
17357 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17358 print REPORT $Report;
17359 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017360 }
17361}
17362
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017363sub getReport($)
17364{
17365 my $Level = $_[0];
17366 if($ReportFormat eq "xml")
17367 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017368 if($Level eq "Join")
17369 {
17370 my $Report = "<reports>\n";
17371 $Report .= getReport("Binary");
17372 $Report .= getReport("Source");
17373 $Report .= "</reports>\n";
17374 return $Report;
17375 }
17376 else
17377 {
17378 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17379 my ($Summary, $MetaData) = get_Summary($Level);
17380 $Report .= $Summary."\n";
17381 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17382 $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 +040017383
17384 # additional symbols info (if needed)
17385 # $Report .= get_Report_SymbolsInfo($Level);
17386
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017387 $Report .= "</report>\n";
17388 return $Report;
17389 }
17390 }
17391 else
17392 { # HTML
17393 my $CssStyles = readModule("Styles", "Report.css");
17394 my $JScripts = readModule("Scripts", "Sections.js");
17395 if($Level eq "Join")
17396 {
17397 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17398 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017399 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
17400 my $Keywords = $TargetTitle.", compatibility, API, report";
17401 my $Description = "Compatibility report for the $TargetTitle $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017402 my ($BSummary, $BMetaData) = get_Summary("Binary");
17403 my ($SSummary, $SMetaData) = get_Summary("Source");
17404 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 +030017405 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017406 <br/><div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017407 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17408 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017409 </div>";
17410 $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>";
17411 $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 Ponomarenko01e8e502015-08-21 22:08:40 +030017412 $Report .= getReportFooter("Double");
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017413 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017414 return $Report;
17415 }
17416 else
17417 {
17418 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017419 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17420 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17421 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 +040017422 if($Level eq "Binary")
17423 {
17424 if(getArch(1) eq getArch(2)
17425 and getArch(1) ne "unknown") {
17426 $Description .= " on ".showArch(getArch(1));
17427 }
17428 }
17429 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 +030017430 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017431 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17432 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17433 $Report .= get_SourceInfo();
17434 $Report .= "</div>\n<br/><br/><br/><hr/>\n";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017435 $Report .= getReportFooter("Single");
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017436 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017437 return $Report;
17438 }
17439 }
17440}
17441
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017442sub getLegend()
17443{
17444 return "<br/>
17445<table class='summary'>
17446<tr>
17447 <td class='new'>added</td>
17448 <td class='passed'>compatible</td>
17449</tr>
17450<tr>
17451 <td class='warning'>warning</td>
17452 <td class='failed'>incompatible</td>
17453</tr></table>\n";
17454}
17455
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017456sub createReport()
17457{
17458 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017459 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017460 writeReport("Join", getReport("Join"));
17461 }
17462 elsif($DoubleReport)
17463 { # default
17464 writeReport("Binary", getReport("Binary"));
17465 writeReport("Source", getReport("Source"));
17466 }
17467 elsif($BinaryOnly)
17468 { # --binary
17469 writeReport("Binary", getReport("Binary"));
17470 }
17471 elsif($SourceOnly)
17472 { # --source
17473 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017474 }
17475}
17476
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017477sub getReportFooter($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017478{
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017479 my $Type = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017480 my $Class = "footer";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017481
17482 if($Type eq "Double") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017483 $Class .= " double_report";
17484 }
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017485
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017486 my $Footer = "<div class=\'$Class\' align='right'><i>Generated on ".(localtime time);
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017487 $Footer .= " by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017488 $Footer .= "</i></div>";
17489 $Footer .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017490 return $Footer;
17491}
17492
17493sub get_Report_Problems($$)
17494{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017495 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017496
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017497 my $Report = get_Report_TypeProblems($Severity, $Level);
17498 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017499 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017500 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017501
17502 if($Severity eq "Low" or $Severity eq "Safe") {
17503 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017504 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017505
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017506 if($ReportFormat eq "html")
17507 {
17508 if($Report)
17509 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017510 if($JoinReport)
17511 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017512 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017513 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17514 }
17515 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017516 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017517 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017518 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017519 else
17520 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017521 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017522 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17523 }
17524 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017525 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017526 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017527 }
17528 }
17529 }
17530 return $Report;
17531}
17532
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017533sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017534{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017535 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17536 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17537 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17538 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017539 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17540 <meta name=\"keywords\" content=\"$Keywords\" />
17541 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017542 <title>
17543 $Title
17544 </title>
17545 <style type=\"text/css\">
17546 $Styles
17547 </style>
17548 <script type=\"text/javascript\" language=\"JavaScript\">
17549 <!--
17550 $Scripts
17551 -->
17552 </script>
17553 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017554}
17555
17556sub insertIDs($)
17557{
17558 my $Text = $_[0];
17559 while($Text=~/CONTENT_ID/)
17560 {
17561 if(int($Content_Counter)%2) {
17562 $ContentID -= 1;
17563 }
17564 $Text=~s/CONTENT_ID/c_$ContentID/;
17565 $ContentID += 1;
17566 $Content_Counter += 1;
17567 }
17568 return $Text;
17569}
17570
17571sub checkPreprocessedUnit($)
17572{
17573 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017574 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017575 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017576 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017577
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017578 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017579 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017580 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017581 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017582 chomp($Line);
17583 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017584 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017585 $CurHeader = path_format($1, $OSgroup);
17586 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017587 $CurClass = "";
17588
17589 if(index($CurHeader, $TMP_DIR)==0) {
17590 next;
17591 }
17592
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017593 if(substr($CurHeaderName, 0, 1) eq "<")
17594 { # <built-in>, <command-line>, etc.
17595 $CurHeaderName = "";
17596 $CurHeader = "";
17597 }
17598
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017599 if($ExtraInfo)
17600 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017601 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017602 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17603 }
17604 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017605 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017606 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017607 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017608 if($CurHeaderName)
17609 {
17610 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17611 and not $Registered_Headers{$Version}{$CurHeader})
17612 { # not a target
17613 next;
17614 }
17615 if(not is_target_header($CurHeaderName, 1)
17616 and not is_target_header($CurHeaderName, 2))
17617 { # user-defined header
17618 next;
17619 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017620 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017621 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017622
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017623 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017624 {
17625 my ($Name, $Value) = ($1, $2);
17626 if(not $Constants{$Version}{$Name}{"Access"})
17627 {
17628 $Constants{$Version}{$Name}{"Access"} = "public";
17629 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017630 if($CurHeaderName) {
17631 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17632 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017633 }
17634 }
17635 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17636 $Constants{$Version}{$1}{"Access"} = "private";
17637 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017638 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017639 else
17640 {
17641 if(defined $ExtraDump)
17642 {
17643 if($Line=~/(\w+)\s*\(/)
17644 { # functions
17645 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17646 }
17647 #elsif($Line=~/(\w+)\s*;/)
17648 #{ # data
17649 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17650 #}
17651 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17652 $CurClass = $2;
17653 }
17654 }
17655 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017656 }
17657 close(PREPROC);
17658 foreach my $Constant (keys(%{$Constants{$Version}}))
17659 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017660 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17661 {
17662 delete($Constants{$Version}{$Constant});
17663 next;
17664 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017665 if(not $ExtraDump and ($Constant=~/_h\Z/i
17666 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017667 { # skip
17668 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017669 }
17670 else {
17671 delete($Constants{$Version}{$Constant}{"Access"});
17672 }
17673 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017674 if($Debug)
17675 {
17676 mkpath($DEBUG_PATH{$Version});
17677 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17678 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017679}
17680
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017681sub uncoverConstant($$)
17682{
17683 my ($LibVersion, $Constant) = @_;
17684 return "" if(not $LibVersion or not $Constant);
17685 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17686 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17687 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17688 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017689
17690 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017691 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017692 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17693 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017694 {
17695 push(@RecurConstant, $Constant);
17696 my $Uncovered = uncoverConstant($LibVersion, $Value);
17697 if($Uncovered ne "") {
17698 $Value = $Uncovered;
17699 }
17700 pop(@RecurConstant);
17701 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017702
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017703 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017704 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017705 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17706 }
17707 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17708}
17709
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017710sub simpleConstant($$)
17711{
17712 my ($LibVersion, $Value) = @_;
17713 if($Value=~/\W/)
17714 {
17715 my $Value_Copy = $Value;
17716 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
17717 {
17718 my $Word = $1;
17719 if($Value!~/$Word\s*\(/)
17720 {
17721 my $Val = uncoverConstant($LibVersion, $Word);
17722 if($Val ne "")
17723 {
17724 $Value=~s/\b$Word\b/$Val/g;
17725 }
17726 }
17727 }
17728 }
17729 return $Value;
17730}
17731
17732sub computeValue($)
17733{
17734 my $Value = $_[0];
17735
17736 if($Value=~/\A\((-?[\d]+)\)\Z/) {
17737 return $1;
17738 }
17739
17740 if($Value=~/\A[\d\-\+()]+\Z/) {
17741 return eval($Value);
17742 }
17743
17744 return $Value;
17745}
17746
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017747my %IgnoreConstant = map {$_=>1} (
17748 "VERSION",
17749 "VERSIONCODE",
17750 "VERNUM",
17751 "VERS_INFO",
17752 "PATCHLEVEL",
17753 "INSTALLPREFIX",
17754 "VBUILD",
17755 "VPATCH",
17756 "VMINOR",
17757 "BUILD_STRING",
17758 "BUILD_TIME",
17759 "PACKAGE_STRING",
17760 "PRODUCTION",
17761 "CONFIGURE_COMMAND",
17762 "INSTALLDIR",
17763 "BINDIR",
17764 "CONFIG_FILE_PATH",
17765 "DATADIR",
17766 "EXTENSION_DIR",
17767 "INCLUDE_PATH",
17768 "LIBDIR",
17769 "LOCALSTATEDIR",
17770 "SBINDIR",
17771 "SYSCONFDIR",
17772 "RELEASE",
17773 "SOURCE_ID",
17774 "SUBMINOR",
17775 "MINOR",
17776 "MINNOR",
17777 "MINORVERSION",
17778 "MAJOR",
17779 "MAJORVERSION",
17780 "MICRO",
17781 "MICROVERSION",
17782 "BINARY_AGE",
17783 "INTERFACE_AGE",
17784 "CORE_ABI",
17785 "PATCH",
17786 "COPYRIGHT",
17787 "TIMESTAMP",
17788 "REVISION",
17789 "PACKAGE_TAG",
17790 "PACKAGEDATE",
17791 "NUMVERSION",
17792 "Release",
17793 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017794);
17795
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017796sub constantFilter($$$)
17797{
17798 my ($Name, $Value, $Level) = @_;
17799
17800 if($Level eq "Binary")
17801 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017802 if($Name=~/_t\Z/)
17803 { # __malloc_ptr_t
17804 return 1;
17805 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017806 foreach (keys(%IgnoreConstant))
17807 {
17808 if($Name=~/(\A|_)$_(_|\Z)/)
17809 { # version
17810 return 1;
17811 }
17812 if(/\A[A-Z].*[a-z]\Z/)
17813 {
17814 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
17815 { # version
17816 return 1;
17817 }
17818 }
17819 }
17820 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
17821 { # version
17822 return 1;
17823 }
17824 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
17825 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
17826 return 1;
17827 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017828
17829 if($Value=~/\A["'].*['"]/i)
17830 { # string
17831 return 0;
17832 }
17833
17834 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
17835 { # static int gcry_pth_init
17836 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017837 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017838 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017839 return 1;
17840 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017841 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017842 { # foo(p)
17843 return 1;
17844 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017845 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017846 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017847 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017848 return 1;
17849 }
17850 }
17851
17852 return 0;
17853}
17854
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017855sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017856{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017857 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017858 foreach my $Constant (keys(%{$Constants{1}}))
17859 {
17860 if($SkipConstants{1}{$Constant})
17861 { # skipped by the user
17862 next;
17863 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017864
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017865 if(my $Header = $Constants{1}{$Constant}{"Header"})
17866 {
17867 if(not is_target_header($Header, 1)
17868 and not is_target_header($Header, 2))
17869 { # user-defined header
17870 next;
17871 }
17872 }
17873 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017874 next;
17875 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017876
17877 my $Old_Value = uncoverConstant(1, $Constant);
17878
17879 if(constantFilter($Constant, $Old_Value, $Level))
17880 { # separate binary and source problems
17881 next;
17882 }
17883
17884 if(not defined $Constants{2}{$Constant}{"Value"})
17885 { # removed
17886 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
17887 "Target"=>$Constant,
17888 "Old_Value"=>$Old_Value );
17889 next;
17890 }
17891
17892 if($Constants{2}{$Constant}{"Value"} eq "")
17893 { # empty value
17894 # TODO: implement a rule
17895 next;
17896 }
17897
17898 my $New_Value = uncoverConstant(2, $Constant);
17899
17900 my $Old_Value_Pure = $Old_Value;
17901 my $New_Value_Pure = $New_Value;
17902
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017903 $Old_Value_Pure=~s/(\W)\s+/$1/g;
17904 $Old_Value_Pure=~s/\s+(\W)/$1/g;
17905 $New_Value_Pure=~s/(\W)\s+/$1/g;
17906 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017907
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017908 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017909
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017910 if($New_Value_Pure ne $Old_Value_Pure)
17911 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017912 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
17913 { # complex values
17914 next;
17915 }
17916 if(computeValue($Old_Value) eq computeValue($New_Value))
17917 { # expressions
17918 next;
17919 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017920 if(convert_integer($Old_Value) eq convert_integer($New_Value))
17921 { # 0x0001 and 0x1, 0x1 and 1 equal constants
17922 next;
17923 }
17924 if($Old_Value eq "0" and $New_Value eq "NULL")
17925 { # 0 => NULL
17926 next;
17927 }
17928 if($Old_Value eq "NULL" and $New_Value eq "0")
17929 { # NULL => 0
17930 next;
17931 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017932 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017933 "Target"=>$Constant,
17934 "Old_Value"=>$Old_Value,
17935 "New_Value"=>$New_Value );
17936 }
17937 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017938
17939 foreach my $Constant (keys(%{$Constants{2}}))
17940 {
17941 if(not defined $Constants{1}{$Constant}{"Value"})
17942 {
17943 if($SkipConstants{2}{$Constant})
17944 { # skipped by the user
17945 next;
17946 }
17947
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017948 if(my $Header = $Constants{2}{$Constant}{"Header"})
17949 {
17950 if(not is_target_header($Header, 1)
17951 and not is_target_header($Header, 2))
17952 { # user-defined header
17953 next;
17954 }
17955 }
17956 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017957 next;
17958 }
17959
17960 my $New_Value = uncoverConstant(2, $Constant);
17961 if(not defined $New_Value or $New_Value eq "") {
17962 next;
17963 }
17964
17965 if(constantFilter($Constant, $New_Value, $Level))
17966 { # separate binary and source problems
17967 next;
17968 }
17969
17970 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
17971 "Target"=>$Constant,
17972 "New_Value"=>$New_Value );
17973 }
17974 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017975}
17976
17977sub convert_integer($)
17978{
17979 my $Value = $_[0];
17980 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017981 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017982 return hex($Value);
17983 }
17984 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017985 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017986 return oct($Value);
17987 }
17988 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017989 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017990 return oct($Value);
17991 }
17992 else {
17993 return $Value;
17994 }
17995}
17996
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017997sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017998{
17999 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018000 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018001 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018002 {
18003 if($LibVersion==1)
18004 {
18005 printMsg("WARNING", "checking headers only");
18006 $CheckHeadersOnly = 1;
18007 }
18008 else {
18009 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18010 }
18011 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018012
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018013 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018014 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018015 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018016
18017 if($CheckUndefined)
18018 {
18019 my %UndefinedLibs = ();
18020
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018021 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18022
18023 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018024 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018025 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018026 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018027 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018028 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018029 if($Symbol_Library{$LibVersion}{$Symbol}
18030 or $DepSymbol_Library{$LibVersion}{$Symbol})
18031 { # exported by target library
18032 next;
18033 }
18034 if(index($Symbol, '@')!=-1)
18035 { # exported default symbol version (@@)
18036 $Symbol=~s/\@/\@\@/;
18037 if($Symbol_Library{$LibVersion}{$Symbol}
18038 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18039 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018040 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018041 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018042 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18043 $UndefinedLibs{$Path} = 1;
18044 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018045 }
18046 }
18047 }
18048 if($ExtraInfo)
18049 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018050 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018051 {
18052 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018053 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018054 foreach (@Paths)
18055 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018056 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018057 my ($Dir, $Name) = separate_path($_);
18058
18059 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018060 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018061 }
18062
18063 $Name = parse_libname($Name, "name", $OStarget);
18064 $Name=~s/\Alib//;
18065
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018066 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018067 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018068
18069 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18070 {
18071 $LibString = " -L".esc($Dir).$LibString;
18072 }
18073
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018074 writeFile($ExtraInfo."/libs-string", $LibString);
18075 }
18076 }
18077 }
18078
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018079 if($ExtraInfo) {
18080 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18081 }
18082
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018083 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018084 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018085 if($#LibPaths!=-1)
18086 {
18087 if(not keys(%{$Symbol_Library{$LibVersion}}))
18088 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018089 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018090 printMsg("WARNING", "checking headers only");
18091 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018092 }
18093 }
18094 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018095
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018096 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018097 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018098}
18099
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018100my %Prefix_Lib_Map=(
18101 # symbols for autodetecting library dependencies (by prefix)
18102 "pthread_" => ["libpthread"],
18103 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18104 "cairo_" => ["libcairo"],
18105 "gtk_" => ["libgtk-x11-2.0"],
18106 "atk_" => ["libatk-1.0"],
18107 "gdk_" => ["libgdk-x11-2.0"],
18108 "gl" => ["libGL"],
18109 "glu" => ["libGLU"],
18110 "popt" => ["libpopt"],
18111 "Py" => ["libpython"],
18112 "jpeg_" => ["libjpeg"],
18113 "BZ2_" => ["libbz2"],
18114 "Fc" => ["libfontconfig"],
18115 "Xft" => ["libXft"],
18116 "SSL_" => ["libssl"],
18117 "sem_" => ["libpthread"],
18118 "snd_" => ["libasound"],
18119 "art_" => ["libart_lgpl_2"],
18120 "dbus_g" => ["libdbus-glib-1"],
18121 "GOMP_" => ["libgomp"],
18122 "omp_" => ["libgomp"],
18123 "cms" => ["liblcms"]
18124);
18125
18126my %Pattern_Lib_Map=(
18127 "SL[a-z]" => ["libslang"]
18128);
18129
18130my %Symbol_Lib_Map=(
18131 # symbols for autodetecting library dependencies (by name)
18132 "pow" => "libm",
18133 "fmod" => "libm",
18134 "sin" => "libm",
18135 "floor" => "libm",
18136 "cos" => "libm",
18137 "dlopen" => "libdl",
18138 "deflate" => "libz",
18139 "inflate" => "libz",
18140 "move_panel" => "libpanel",
18141 "XOpenDisplay" => "libX11",
18142 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018143 "clock_gettime" => "librt",
18144 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018145);
18146
18147sub find_SymbolLibs($$)
18148{
18149 my ($LibVersion, $Symbol) = @_;
18150
18151 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18152 { # debug symbols
18153 return ();
18154 }
18155
18156 my %Paths = ();
18157
18158 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18159 {
18160 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18161 $Paths{$Path} = 1;
18162 }
18163 }
18164
18165 if(my $SymbolPrefix = getPrefix($Symbol))
18166 {
18167 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18168 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18169 }
18170
18171 if(not keys(%Paths))
18172 {
18173 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18174 {
18175 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18176 {
18177 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18178 $Paths{$Path} = 1;
18179 }
18180 }
18181 }
18182 }
18183
18184 if(not keys(%Paths))
18185 {
18186 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18187 {
18188 if($Symbol=~/\A$Prefix/)
18189 {
18190 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18191 {
18192 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18193 $Paths{$Path} = 1;
18194 }
18195 }
18196 }
18197 }
18198 }
18199
18200 if(not keys(%Paths))
18201 {
18202 if($SymbolPrefix)
18203 { # try to find a library by symbol prefix
18204 if($SymbolPrefix eq "inotify" and
18205 index($Symbol, "\@GLIBC")!=-1)
18206 {
18207 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18208 $Paths{$Path} = 1;
18209 }
18210 }
18211 else
18212 {
18213 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18214 $Paths{$Path} = 1;
18215 }
18216 }
18217 }
18218 }
18219
18220 if(my @Paths = keys(%Paths)) {
18221 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18222 }
18223 }
18224 return keys(%Paths);
18225}
18226
18227sub get_LibPath_Prefix($$)
18228{
18229 my ($LibVersion, $Prefix) = @_;
18230
18231 $Prefix = lc($Prefix);
18232 $Prefix=~s/[_]+\Z//g;
18233
18234 foreach ("-2", "2", "-1", "1", "")
18235 { # libgnome-2.so
18236 # libxml2.so
18237 # libdbus-1.so
18238 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18239 return $Path;
18240 }
18241 }
18242 return "";
18243}
18244
18245sub getPrefix($)
18246{
18247 my $Str = $_[0];
18248 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18249 { # XmuValidArea: Xmu
18250 return $1;
18251 }
18252 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18253 { # snfReadFont: snf
18254 return $1;
18255 }
18256 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18257 { # XRRTimes: XRR
18258 return $1;
18259 }
18260 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18261 { # H5HF_delete: H5
18262 return $1;
18263 }
18264 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18265 { # alarm_event_add: alarm_
18266 return $1;
18267 }
18268 elsif($Str=~/\A(([a-z])\2{1,})/i)
18269 { # ffopen
18270 return $1;
18271 }
18272 return "";
18273}
18274
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018275sub getSymbolSize($$)
18276{ # size from the shared library
18277 my ($Symbol, $LibVersion) = @_;
18278 return 0 if(not $Symbol);
18279 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18280 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18281 {
18282 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18283 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18284 {
18285 if($Size<0) {
18286 return -$Size;
18287 }
18288 }
18289 }
18290 return 0;
18291}
18292
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018293sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018294{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18295 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018296 my ($Name, $Type) = @_;
18297
18298 # single
18299 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018300 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018301 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018302 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018303 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018304
18305 # double
18306 if($Name=~/$DEFAULT_STD_PARMS/)
18307 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018308 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018309 {
18310 my ($ShortName, $FuncParams) = split_Signature($Name);
18311
18312 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18313 {
18314 if(index($FParam, "<")!=-1)
18315 {
18316 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18317 my $FParam_N = canonifyName($FParam, "T");
18318 if($FParam_N ne $FParam) {
18319 $Name=~s/\Q$FParam\E/$FParam_N/g;
18320 }
18321 }
18322 }
18323 }
18324 elsif($Type eq "T")
18325 {
18326 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18327
18328 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018329 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018330 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018331 my $FParam = $TParams[0];
18332 foreach my $Pos (1 .. $#TParams)
18333 {
18334 my $TParam = $TParams[$Pos];
18335 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18336 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18337 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018338 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018339 }
18340 }
18341 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018342 if($Type eq "S") {
18343 return formatName($Name, "S");
18344 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018345 return $Name;
18346}
18347
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018348sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018349{
18350 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018351 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018352 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018353 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018354 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018355 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018356 next if($tr_name{$Symbol});
18357 $Symbol=~s/[\@\$]+(.*)\Z//;
18358 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018359 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018360 elsif(index($Symbol, "?")==0)
18361 {
18362 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018363 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018364 }
18365 else
18366 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018367 $tr_name{$Symbol} = $Symbol;
18368 $mangled_name_gcc{$Symbol} = $Symbol;
18369 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018370 }
18371 }
18372 if($#MnglNames1 > -1)
18373 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018374 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018375 foreach my $MnglName (@MnglNames1)
18376 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018377 if(my $Unmangled = pop(@UnmangledNames))
18378 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018379 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018380 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18381 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18382 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018383 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018384 and $tr_name{$MnglName}=~/vtable for (.+)/)
18385 { # bind class name and v-table symbol
18386 my $ClassName = $1;
18387 $ClassVTable{$ClassName} = $MnglName;
18388 $VTableClass{$MnglName} = $ClassName;
18389 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018390 }
18391 }
18392 }
18393 if($#MnglNames2 > -1)
18394 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018395 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018396 foreach my $MnglName (@MnglNames2)
18397 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018398 if(my $Unmangled = pop(@UnmangledNames))
18399 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018400 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018401 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18402 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018403 }
18404 }
18405 return \%tr_name;
18406}
18407
18408sub link_symbol($$$)
18409{
18410 my ($Symbol, $RunWith, $Deps) = @_;
18411 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18412 return 1;
18413 }
18414 if($Deps eq "+Deps")
18415 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018416 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018417 return 1;
18418 }
18419 }
18420 return 0;
18421}
18422
18423sub link_symbol_internal($$$)
18424{
18425 my ($Symbol, $RunWith, $Where) = @_;
18426 return 0 if(not $Where or not $Symbol);
18427 if($Where->{$RunWith}{$Symbol})
18428 { # the exact match by symbol name
18429 return 1;
18430 }
18431 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18432 { # indirect symbol version, i.e.
18433 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018434 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018435 if($Where->{$RunWith}{$VSym}) {
18436 return 1;
18437 }
18438 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018439 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018440 if($Sym and $Ver)
18441 { # search for the symbol with the same version
18442 # or without version
18443 if($Where->{$RunWith}{$Sym})
18444 { # old: foo@v|foo@@v
18445 # new: foo
18446 return 1;
18447 }
18448 if($Where->{$RunWith}{$Sym."\@".$Ver})
18449 { # old: foo|foo@@v
18450 # new: foo@v
18451 return 1;
18452 }
18453 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18454 { # old: foo|foo@v
18455 # new: foo@@v
18456 return 1;
18457 }
18458 }
18459 return 0;
18460}
18461
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018462sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018463{
18464 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018465 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018466 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018467 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018468 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018469 my $NM = get_CmdPath("nm");
18470 if(not $NM) {
18471 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018472 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018473 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018474 while(<APP>)
18475 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018476 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018477 push(@Imported, $1);
18478 }
18479 }
18480 close(APP);
18481 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018482 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018483 {
18484 my $DumpBinCmd = get_CmdPath("dumpbin");
18485 if(not $DumpBinCmd) {
18486 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18487 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018488 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018489 while(<APP>)
18490 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018491 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18492 push(@Imported, $1);
18493 }
18494 }
18495 close(APP);
18496 }
18497 else
18498 {
18499 my $ReadelfCmd = get_CmdPath("readelf");
18500 if(not $ReadelfCmd) {
18501 exitStatus("Not_Found", "can't find \"readelf\"");
18502 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018503 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018504 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018505 while(<APP>)
18506 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018507 if(defined $symtab)
18508 { # do nothing with symtab
18509 if(index($_, "'.dynsym'")!=-1)
18510 { # dynamic table
18511 $symtab = undef;
18512 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018513 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018514 elsif(index($_, "'.symtab'")!=-1)
18515 { # symbol table
18516 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018517 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018518 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018519 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018520 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18521 if($Ndx eq "UND")
18522 { # only imported symbols
18523 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018524 }
18525 }
18526 }
18527 close(APP);
18528 }
18529 return @Imported;
18530}
18531
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018532my %ELF_BIND = map {$_=>1} (
18533 "WEAK",
18534 "GLOBAL"
18535);
18536
18537my %ELF_TYPE = map {$_=>1} (
18538 "FUNC",
18539 "IFUNC",
18540 "OBJECT",
18541 "COMMON"
18542);
18543
18544my %ELF_VIS = map {$_=>1} (
18545 "DEFAULT",
18546 "PROTECTED"
18547);
18548
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018549sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018550{ # read the line of 'readelf' output corresponding to the symbol
18551 my @Info = split(/\s+/, $_[0]);
18552 # Num: Value Size Type Bind Vis Ndx Name
18553 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018554 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018555 shift(@Info); # spaces
18556 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018557
18558 if($#Info==7)
18559 { # UND SYMBOL (N)
18560 if($Info[7]=~/\(\d+\)/) {
18561 pop(@Info);
18562 }
18563 }
18564
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018565 if($#Info!=6)
18566 { # other lines
18567 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018568 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018569 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018570 return () if(not defined $ELF_BIND{$Info[3]});
18571 return () if(not defined $ELF_VIS{$Info[4]});
18572 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18573 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18574 return ();
18575 }
18576 if($OStarget eq "symbian")
18577 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18578 if(index($Info[6], "_._.absent_export_")!=-1)
18579 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18580 return ();
18581 }
18582 $Info[6]=~s/\@.+//g; # remove version
18583 }
18584 if(index($Info[2], "0x") == 0)
18585 { # size == 0x3d158
18586 $Info[2] = hex($Info[2]);
18587 }
18588 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018589}
18590
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018591sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018592{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018593 my ($LibVersion, $Name) = @_;
18594 return "" if(not $LibVersion or not $Name);
18595 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18596 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018597 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018598 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18599}
18600
18601sub get_LibPath_I($$)
18602{
18603 my ($LibVersion, $Name) = @_;
18604 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018605 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018606 if(-f $Name)
18607 { # absolute path
18608 return $Name;
18609 }
18610 else
18611 { # broken
18612 return "";
18613 }
18614 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018615 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018616 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018617 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018618 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018619 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018620 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018621 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018622 }
18623 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18624 { # ldconfig default paths
18625 return $DefaultPath;
18626 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018627 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018628 { # search in default linker directories
18629 # and then in all system paths
18630 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018631 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018632 }
18633 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018634 if(not defined $Cache{"checkSystemFiles"}) {
18635 checkSystemFiles();
18636 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018637 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18638 return $AllObjects[0];
18639 }
18640 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18641 {
18642 if($ShortName ne $Name)
18643 { # FIXME: check this case
18644 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18645 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018646 }
18647 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018648 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018649 # can't find
18650 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018651}
18652
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018653sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018654{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018655 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18656 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018657
18658 my $Real_Path = realpath($Lib_Path);
18659
18660 if(not $Real_Path)
18661 { # broken link
18662 return ();
18663 }
18664
18665 my $Lib_Name = get_filename($Real_Path);
18666
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018667 if($ExtraInfo)
18668 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018669 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018670 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018671 }
18672
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018673 if($IsNeededLib)
18674 {
18675 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18676 return ();
18677 }
18678 }
18679 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018680 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018681
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018682 push(@RecurLib, $Lib_Name);
18683 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018684 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18685
18686 if(not $IsNeededLib)
18687 { # special cases: libstdc++ and libc
18688 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18689 {
18690 if($ShortName eq "libstdc++")
18691 { # libstdc++.so.6
18692 $STDCXX_TESTING = 1;
18693 }
18694 elsif($ShortName eq "libc")
18695 { # libc-2.11.3.so
18696 $GLIBC_TESTING = 1;
18697 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018698 }
18699 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018700 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018701 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018702 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018703 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018704 mkpath(get_dirname($DebugPath));
18705 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018706 if($OStarget eq "macos")
18707 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018708 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018709 if(not $NM) {
18710 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018711 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018712 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018713 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018714 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018715 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018716 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018717 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018718 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018719 else
18720 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018721 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018722 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018723 while(<LIB>)
18724 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018725 if($CheckUndefined)
18726 {
18727 if(not $IsNeededLib)
18728 {
18729 if(/ U _([\w\$]+)\s*\Z/)
18730 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018731 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018732 next;
18733 }
18734 }
18735 }
18736
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018737 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018738 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018739 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018740 if($IsNeededLib)
18741 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018742 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018743 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018744 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18745 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018746 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018747 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018748 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018749 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018750 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18751 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018752 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18753 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018754 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018755 setLanguage($LibVersion, "C++");
18756 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018757 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018758 }
18759 }
18760 }
18761 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018762
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018763 if($Deps)
18764 {
18765 if($LIB_TYPE eq "dynamic")
18766 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018767
18768 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018769 if(not $OtoolCmd) {
18770 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018771 }
18772
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018773 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18774 while(<LIB>)
18775 {
18776 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
18777 and $1 ne $Lib_Path) {
18778 $NeededLib{$1} = 1;
18779 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018780 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018781 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018782 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018783 }
18784 }
18785 elsif($OStarget eq "windows")
18786 { # Windows *.dll, *.lib
18787 my $DumpBinCmd = get_CmdPath("dumpbin");
18788 if(not $DumpBinCmd) {
18789 exitStatus("Not_Found", "can't find \"dumpbin\"");
18790 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018791 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018792 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018793 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018794 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018795 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018796 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018797 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018798 else
18799 { # write to pipe
18800 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018801 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018802 while(<LIB>)
18803 { # 1197 4AC 0000A620 SetThreadStackGuarantee
18804 # 1198 4AD SetThreadToken (forwarded to ...)
18805 # 3368 _o2i_ECPublicKey
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018806 # 1 0 00005B30 ??0?N = ... (with pdb)
18807 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018808 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018809 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018810 { # dynamic, static and forwarded symbols
18811 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018812 if($IsNeededLib)
18813 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018814 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018815 {
18816 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
18817 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
18818 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018819 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018820 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018821 {
18822 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
18823 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018824 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18825 {
18826 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
18827 setLanguage($LibVersion, "C++");
18828 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018829 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018830 }
18831 }
18832 }
18833 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018834
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018835 if($Deps)
18836 {
18837 if($LIB_TYPE eq "dynamic")
18838 { # dependencies
18839 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18840 while(<LIB>)
18841 {
18842 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
18843 and $1 ne $Lib_Path) {
18844 $NeededLib{path_format($1, $OSgroup)} = 1;
18845 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018846 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018847 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018848 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018849 }
18850 }
18851 else
18852 { # Unix; *.so, *.a
18853 # Symbian: *.dso, *.lib
18854 my $ReadelfCmd = get_CmdPath("readelf");
18855 if(not $ReadelfCmd) {
18856 exitStatus("Not_Found", "can't find \"readelf\"");
18857 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018858 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018859 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018860 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018861 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018862 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018863 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018864 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018865 else
18866 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018867 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018868 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018869 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018870 while(<LIB>)
18871 {
18872 if($LIB_TYPE eq "dynamic")
18873 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018874 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018875 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018876 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018877 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018878 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018879 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018880 # do nothing with symtab
18881 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018882 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018883 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018884 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018885 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018886 next;
18887 }
18888 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018889 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018890 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018891 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018892 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018893 if($CheckUndefined)
18894 {
18895 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018896 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018897 }
18898 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018899 next;
18900 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040018901 if($Bind eq "WEAK")
18902 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018903 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040018904 if($Weak eq "-Weak")
18905 { # skip WEAK symbols
18906 next;
18907 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018908 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018909 my $Short = $Symbol;
18910 $Short=~s/\@.+//g;
18911 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018912 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018913 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
18914 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018915 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018916 if($IsNeededLib)
18917 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018918 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018919 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018920 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18921 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018922 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018923 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018924 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018925 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018926 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18927 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
18928 if($Vers)
18929 {
18930 if($LIB_EXT eq "so")
18931 { # value
18932 $Interface_Value{$LibVersion}{$Symbol} = $Value;
18933 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
18934 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018935 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018936 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18937 {
18938 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
18939 setLanguage($LibVersion, "C++");
18940 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018941 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018942 }
18943 }
18944 }
18945 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018946
18947 if($Deps and $LIB_TYPE eq "dynamic")
18948 { # dynamic library specifics
18949 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
18950 open(LIB, $Cmd." |");
18951
18952 while(<LIB>)
18953 {
18954 if(/NEEDED.+\[([^\[\]]+)\]/)
18955 { # dependencies:
18956 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
18957 $NeededLib{$1} = 1;
18958 }
18959 }
18960
18961 close(LIB);
18962 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018963 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018964 if($Vers)
18965 {
18966 if(not $IsNeededLib and $LIB_EXT eq "so")
18967 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018968 my %Found = ();
18969
18970 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018971 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018972 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018973 next if(index($Symbol,"\@")==-1);
18974 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018975 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018976 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018977 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018978 if($Symbol_SameValue ne $Symbol
18979 and index($Symbol_SameValue,"\@")==-1)
18980 {
18981 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018982 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018983 last;
18984 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018985 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018986 }
18987 }
18988
18989 # default
18990 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
18991 {
18992 next if(defined $Found{$Symbol});
18993 next if(index($Symbol,"\@\@")==-1);
18994
18995 if($Symbol=~/\A([^\@]*)\@\@/
18996 and not $SymVer{$LibVersion}{$1})
18997 {
18998 $SymVer{$LibVersion}{$1} = $Symbol;
18999 $Found{$Symbol} = 1;
19000 }
19001 }
19002
19003 # non-default
19004 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19005 {
19006 next if(defined $Found{$Symbol});
19007 next if(index($Symbol,"\@")==-1);
19008
19009 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19010 and not $SymVer{$LibVersion}{$1})
19011 {
19012 $SymVer{$LibVersion}{$1} = $Symbol;
19013 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019014 }
19015 }
19016 }
19017 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019018 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019019 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019020 foreach my $DyLib (sort keys(%NeededLib))
19021 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019022 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19023
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019024 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19025 {
19026 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19027 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19028 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019029 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019030 }
19031 }
19032 pop(@RecurLib);
19033 return $Library_Symbol{$LibVersion};
19034}
19035
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019036sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019037{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019038 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019039 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019040 return keys(%Prefixes);
19041}
19042
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019043sub get_prefixes_I($$)
19044{
19045 foreach my $P (@{$_[0]})
19046 {
19047 my @Parts = reverse(split(/[\/\\]+/, $P));
19048 my $Name = $Parts[0];
19049 foreach (1 .. $#Parts)
19050 {
19051 $_[1]->{$Name}{$P} = 1;
19052 last if($_>4 or $Parts[$_] eq "include");
19053 $Name = $Parts[$_].$SLASH.$Name;
19054 }
19055 }
19056}
19057
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019058sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019059{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019060 $Cache{"checkSystemFiles"} = 1;
19061
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019062 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019063
19064 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019065 {
19066 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019067
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019068 my @Files = cmd_find($DevelPath,"f");
19069 foreach my $Link (cmd_find($DevelPath,"l"))
19070 { # add symbolic links
19071 if(-f $Link) {
19072 push(@Files, $Link);
19073 }
19074 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019075
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019076 # search for headers in /usr/lib
19077 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19078 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19079 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019080
19081 # search for libraries in /usr/lib (including symbolic links)
19082 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19083 foreach my $Path (@Libs)
19084 {
19085 my $N = get_filename($Path);
19086 $SystemObjects{$N}{$Path} = 1;
19087 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019088 }
19089 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019090
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019091 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019092 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019093 next if(not -d $DevelPath);
19094 # search for all header files in the /usr/include
19095 # with or without extension (ncurses.h, QtCore, ...)
19096 push(@SysHeaders, cmd_find($DevelPath,"f"));
19097 foreach my $Link (cmd_find($DevelPath,"l"))
19098 { # add symbolic links
19099 if(-f $Link) {
19100 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019101 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019102 }
19103 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019104 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019105}
19106
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019107sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019108{
19109 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019110 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019111 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19112 {
19113 if(not -e $Dest) {
19114 exitStatus("Access_Error", "can't access \'$Dest\'");
19115 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019116 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019117 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19118 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019119 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019120 }
19121 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019122 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019123}
19124
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019125sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019126{
19127 my ($Path, $LibVersion) = @_;
19128 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019129 my $Name = get_filename($Path);
19130 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019131 return 1;
19132 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019133 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019134 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19135 return 1;
19136 }
19137 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19138 {
19139 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19140 return 1;
19141 }
19142 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019143 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019144 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019145 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019146 return 1;
19147 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019148 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019149 return 1;
19150 }
19151 }
19152 return 0;
19153}
19154
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019155sub specificHeader($$)
19156{
19157 my ($Header, $Spec) = @_;
19158 my $Name = get_filename($Header);
19159
19160 if($Spec eq "windows")
19161 {# MS Windows
19162 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19163 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19164 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19165 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19166 my @Dirs = (
19167 "win32",
19168 "win64",
19169 "win",
19170 "windows",
19171 "msvcrt"
19172 ); # /gsf-win32/
19173 if(my $DIRs = join("|", @Dirs)) {
19174 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19175 }
19176 }
19177 elsif($Spec eq "macos")
19178 { # Mac OS
19179 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19180 }
19181
19182 return 0;
19183}
19184
19185sub skipAlienHeader($)
19186{
19187 my $Path = $_[0];
19188 my $Name = get_filename($Path);
19189 my $Dir = get_dirname($Path);
19190
19191 if($Tolerance=~/2/)
19192 { # 2 - skip internal headers
19193 my @Terms = (
19194 "p",
19195 "priv",
19196 "int",
19197 "impl",
19198 "implementation",
19199 "internal",
19200 "private",
19201 "old",
19202 "compat",
19203 "debug",
19204 "test",
19205 "gen"
19206 );
19207
19208 my @Dirs = (
19209 "private",
19210 "priv",
19211 "port",
19212 "impl",
19213 "internal",
19214 "detail",
19215 "details",
19216 "old",
19217 "compat",
19218 "debug",
19219 "config",
19220 "compiler",
19221 "platform",
19222 "test"
19223 );
19224
19225 if(my $TERMs = join("|", @Terms)) {
19226 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19227 }
19228 if(my $DIRs = join("|", @Dirs)) {
19229 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19230 }
19231
19232 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19233 }
19234
19235 if($Tolerance=~/1/)
19236 { # 1 - skip non-Linux headers
19237 if($OSgroup ne "windows")
19238 {
19239 if(specificHeader($Path, "windows")) {
19240 return 1;
19241 }
19242 }
19243 if($OSgroup ne "macos")
19244 {
19245 if(specificHeader($Path, "macos")) {
19246 return 1;
19247 }
19248 }
19249 }
19250
19251 # valid
19252 return 0;
19253}
19254
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019255sub skipHeader($$)
19256{
19257 my ($Path, $LibVersion) = @_;
19258 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019259 if(defined $Cache{"skipHeader"}{$Path}) {
19260 return $Cache{"skipHeader"}{$Path};
19261 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019262 if(defined $Tolerance and $Tolerance=~/1|2/)
19263 { # --tolerant
19264 if(skipAlienHeader($Path)) {
19265 return ($Cache{"skipHeader"}{$Path} = 1);
19266 }
19267 }
19268 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19269 return 0;
19270 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019271 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19272}
19273
19274sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019275{ # returns:
19276 # 1 - if header should NOT be included and checked
19277 # 2 - if header should NOT be included, but should be checked
19278 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019279 my $Name = get_filename($Path);
19280 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019281 return $Kind;
19282 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019283 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19284 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019285 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019286 if(index($Path, $D)!=-1)
19287 {
19288 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19289 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19290 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019291 }
19292 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019293 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19294 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019295 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019296 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19297 {
19298 if($Name=~/$P/) {
19299 return $Kind;
19300 }
19301 if($P=~/[\/\\]/ and $Path=~/$P/) {
19302 return $Kind;
19303 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019304 }
19305 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019306
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019307 return 0;
19308}
19309
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019310sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019311{
19312 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019313 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019314 { # system directory
19315 return;
19316 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019317 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019318 { # already registered
19319 return;
19320 }
19321 foreach my $Path (find_libs($Dir,"",1))
19322 {
19323 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019324 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019325 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019326 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019327 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19328}
19329
19330sub registerObject($$)
19331{
19332 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019333
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019334 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019335 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019336 if($OStarget=~/linux|bsd/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019337 {
19338 if(my $SONAME = getSONAME($Path)) {
19339 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19340 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019341 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019342 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19343 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019344 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019345
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019346 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019347 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019348 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019349 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019350 if($ObjArch ne getArch_GCC($LibVersion))
19351 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19352 $CheckedArch{$LibVersion} = 1;
19353 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 +040019354 }
19355 }
19356 }
19357}
19358
19359sub getArch_Object($)
19360{
19361 my $Path = $_[0];
19362
19363 my %MachineType = (
19364 "14C" => "x86",
19365 "8664" => "x86_64",
19366 "1C0" => "arm",
19367 "200" => "ia64"
19368 );
19369
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019370 my %ArchName = (
19371 "s390:31-bit" => "s390",
19372 "s390:64-bit" => "s390x",
19373 "powerpc:common" => "ppc32",
19374 "powerpc:common64" => "ppc64",
19375 "i386:x86-64" => "x86_64",
19376 "mips:3000" => "mips",
19377 "sparc:v8plus" => "sparcv9"
19378 );
19379
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019380 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019381 {
19382 my $DumpbinCmd = get_CmdPath("dumpbin");
19383 if(not $DumpbinCmd) {
19384 exitStatus("Not_Found", "can't find \"dumpbin\"");
19385 }
19386
19387 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19388 my $Out = `$Cmd`;
19389
19390 if($Out=~/(\w+)\smachine/)
19391 {
19392 if(my $Type = $MachineType{uc($1)})
19393 {
19394 return $Type;
19395 }
19396 }
19397 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019398 elsif($OStarget=~/linux|bsd/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019399 {
19400 my $ObjdumpCmd = get_CmdPath("objdump");
19401 if(not $ObjdumpCmd) {
19402 exitStatus("Not_Found", "can't find \"objdump\"");
19403 }
19404
19405 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019406
19407 if($OSgroup eq "windows") {
19408 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19409 }
19410 else {
19411 $Cmd = "LANG=$LOCALE ".$Cmd;
19412 }
19413 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019414
19415 if($Out=~/architecture:\s+([\w\-\:]+)/)
19416 {
19417 my $Arch = $1;
19418 if($Arch=~s/\:(.+)//)
19419 {
19420 my $Suffix = $1;
19421
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019422 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019423 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019424 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019425 }
19426 }
19427
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019428 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019429 $Arch = "x86";
19430 }
19431
19432 if($Arch eq "x86-64") {
19433 $Arch = "x86_64";
19434 }
19435
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019436 if($Arch eq "ia64-elf64") {
19437 $Arch = "ia64";
19438 }
19439
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019440 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019441 }
19442 }
19443 else
19444 { # macos, etc.
19445 # TODO
19446 }
19447
19448 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019449}
19450
19451sub getSONAME($)
19452{
19453 my $Path = $_[0];
19454 return if(not $Path);
19455 if(defined $Cache{"getSONAME"}{$Path}) {
19456 return $Cache{"getSONAME"}{$Path};
19457 }
19458 my $ObjdumpCmd = get_CmdPath("objdump");
19459 if(not $ObjdumpCmd) {
19460 exitStatus("Not_Found", "can't find \"objdump\"");
19461 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019462 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019463 if($OSgroup eq "windows") {
19464 $SonameCmd .= " | find \"SONAME\"";
19465 }
19466 else {
19467 $SonameCmd .= " | grep SONAME";
19468 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019469 if(my $SonameInfo = `$SonameCmd`)
19470 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019471 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19472 return ($Cache{"getSONAME"}{$Path} = $1);
19473 }
19474 }
19475 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019476}
19477
19478sub getSOPaths_Dest($$)
19479{
19480 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019481 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019482 return ();
19483 }
19484 if(-f $Dest)
19485 {
19486 if(not parse_libname($Dest, "name", $OStarget)) {
19487 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19488 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019489 registerObject($Dest, $LibVersion);
19490 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019491 return ($Dest);
19492 }
19493 elsif(-d $Dest)
19494 {
19495 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019496 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019497 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019498 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19499 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019500 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019501 { # all files and symlinks that match the name of a library
19502 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19503 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019504 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019505 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019506 }
19507 }
19508 }
19509 else
19510 { # search for all files and symlinks
19511 foreach my $Path (find_libs($Dest,"",""))
19512 {
19513 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019514 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019515 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019516 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019517 }
19518 if($OSgroup eq "macos")
19519 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019520 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019521 {
19522 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019523 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019524 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019525 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19526 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019527 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019528 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019529 }
19530 }
19531 }
19532 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019533 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019534 }
19535 else {
19536 return ();
19537 }
19538}
19539
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019540sub isCyclical($$)
19541{
19542 my ($Stack, $Value) = @_;
19543 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019544}
19545
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019546sub getGCC_Opts($)
19547{ # to use in module
19548 my $LibVersion = $_[0];
19549
19550 my @Opts = ();
19551
19552 if($CompilerOptions{$LibVersion})
19553 { # user-defined options
19554 push(@Opts, $CompilerOptions{$LibVersion});
19555 }
19556 if($GccOptions)
19557 { # additional
19558 push(@Opts, $GccOptions);
19559 }
19560
19561 if(@Opts) {
19562 return join(" ", @Opts);
19563 }
19564
19565 return undef;
19566}
19567
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019568sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019569{
19570 my $LibVersion = $_[0];
19571
19572 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19573 return $Cache{"getArch_GCC"}{$LibVersion};
19574 }
19575
19576 my $Arch = undef;
19577
19578 if($GCC_PATH)
19579 {
19580 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
19581
19582 my $Cmd = $GCC_PATH." test.c -o test";
19583 if(my $Opts = getGCC_Opts($LibVersion))
19584 { # user-defined options
19585 $Cmd .= " ".$Opts;
19586 }
19587
19588 chdir($TMP_DIR);
19589 system($Cmd);
19590 chdir($ORIG_DIR);
19591
19592 $Arch = getArch_Object("$TMP_DIR/test");
19593
19594 unlink("$TMP_DIR/test.c");
19595 unlink("$TMP_DIR/test");
19596 }
19597
19598 if(not $Arch) {
19599 exitStatus("Error", "can't check ARCH type");
19600 }
19601
19602 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
19603}
19604
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019605sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019606{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019607 my $LibVersion = $_[0];
19608
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019609 my $Size = undef;
19610
19611 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019612 if(my $Arch = getArch($LibVersion))
19613 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019614 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019615 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019616 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019617 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
19618 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019619 }
19620 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019621
19622 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019623 {
19624 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019625
19626 my $Cmd = $GCC_PATH." -E -dD empty.h";
19627 if(my $Opts = getGCC_Opts($LibVersion))
19628 { # user-defined options
19629 $Cmd .= " ".$Opts;
19630 }
19631
19632 chdir($TMP_DIR);
19633 my $Defines = `$Cmd`;
19634 chdir($ORIG_DIR);
19635
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019636 unlink("$TMP_DIR/empty.h");
19637
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019638 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
19639 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019640 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019641 }
19642 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
19643 { # GCC 3
19644 my $PTRDIFF = $1;
19645 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019646 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019647 }
19648 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019649 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019650 }
19651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019652 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019653
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019654 if(not $Size) {
19655 exitStatus("Error", "can't check WORD size");
19656 }
19657
19658 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019659}
19660
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019661sub getWordSize($)
19662{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019663 return $WORD_SIZE{$_[0]};
19664}
19665
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019666sub majorVersion($)
19667{
19668 my $V = $_[0];
19669 return 0 if(not $V);
19670 my @VParts = split(/\./, $V);
19671 return $VParts[0];
19672}
19673
19674sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019675{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019676 my ($V1, $V2) = @_;
19677 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019678 my @V1Parts = split(/\./, $V1);
19679 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019680 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
19681 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019682 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
19683 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
19684 }
19685 return -1 if($#V1Parts < $#V2Parts);
19686 return 1 if($#V1Parts > $#V2Parts);
19687 return 0;
19688}
19689
19690sub read_ABI_Dump($$)
19691{
19692 my ($LibVersion, $Path) = @_;
19693 return if(not $LibVersion or not -e $Path);
19694 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019695 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019696 { # input *.abi
19697 $FilePath = $Path;
19698 }
19699 else
19700 { # input *.abi.tar.gz
19701 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019702 if(not isDump_U($FilePath)) {
19703 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19704 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019705 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019706
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019707 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019708
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019709 my $Line = readLineNum($FilePath, 0);
19710 if($Line=~/xml/)
19711 { # XML format
19712 loadModule("XmlDump");
19713 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019714 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019715 else
19716 { # Perl Data::Dumper format (default)
19717 open(DUMP, $FilePath);
19718 local $/ = undef;
19719 my $Content = <DUMP>;
19720 close(DUMP);
19721
19722 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
19723 { # remove temp file
19724 unlink($FilePath);
19725 }
19726 if($Content!~/};\s*\Z/) {
19727 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19728 }
19729 $ABI = eval($Content);
19730 if(not $ABI) {
19731 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
19732 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019733 }
19734 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019735 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019736 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019737 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019738 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019739 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019740 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019741 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030019742 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019743
19744 if($ABI->{"ABI_DUMP_VERSION"})
19745 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019746 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019747 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019748 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019749 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019750 }
19751 else
19752 { # support for old ABI dumps
19753 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019754 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019755 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019756 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019757 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030019758
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019759 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030019760 {
19761 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 +040019762 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019763
19764 if(defined $ABI->{"ABI_DUMPER_VERSION"})
19765 { # DWARF ABI Dump
19766 $UseConv_Real{$LibVersion}{"P"} = 1;
19767 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19768
19769 $UsedDump{$LibVersion}{"DWARF"} = 1;
19770
19771 $TargetComponent = "module";
19772 }
19773
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019774 if(not checkDump($LibVersion, "2.11"))
19775 { # old ABI dumps
19776 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019777 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019778 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019779 { # ABI dump created with --binary option
19780 $UsedDump{$LibVersion}{"BinOnly"} = 1;
19781 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019782 else
19783 { # default
19784 $UsedDump{$LibVersion}{"SrcBin"} = 1;
19785 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019786
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019787 if(defined $ABI->{"Mode"}
19788 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019789 { # --ext option
19790 $ExtendedCheck = 1;
19791 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019792 if($ABI->{"Extra"}) {
19793 $ExtraDump = 1;
19794 }
19795
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019796 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019797 {
19798 $UsedDump{$LibVersion}{"L"} = $Lang;
19799 setLanguage($LibVersion, $Lang);
19800 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019801 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019802 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019803 }
19804 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019805 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019806 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019807 if(not $TInfo)
19808 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019809 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019810 }
19811 my %Tid_TDid = ();
19812 foreach my $TDid (keys(%{$TInfo}))
19813 {
19814 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
19815 {
19816 $MAX_ID = $Tid if($Tid>$MAX_ID);
19817 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019818 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019819 }
19820 }
19821 my %NewID = ();
19822 foreach my $Tid (keys(%Tid_TDid))
19823 {
19824 my @TDids = keys(%{$Tid_TDid{$Tid}});
19825 if($#TDids>=1)
19826 {
19827 foreach my $TDid (@TDids)
19828 {
19829 if($TDid) {
19830 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19831 }
19832 else
19833 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019834 my $ID = ++$MAX_ID;
19835
19836 $NewID{$TDid}{$Tid} = $ID;
19837 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
19838 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019839 }
19840 }
19841 }
19842 else
19843 {
19844 my $TDid = $TDids[0];
19845 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19846 }
19847 }
19848 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
19849 {
19850 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
19851 if(defined $Info{"BaseType"})
19852 {
19853 my $Bid = $Info{"BaseType"}{"Tid"};
19854 my $BDid = $Info{"BaseType"}{"TDid"};
19855 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019856 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019857 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
19858 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
19859 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019860 }
19861 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
19862 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019863 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019864 read_Machine_DumpInfo($ABI, $LibVersion);
19865 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019866 if(not $SymbolInfo{$LibVersion})
19867 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019868 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019869 }
19870 if(not keys(%{$SymbolInfo{$LibVersion}}))
19871 { # validation of old-version dumps
19872 if(not $ExtendedCheck) {
19873 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
19874 }
19875 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019876 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019877 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019878 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019879 else
19880 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019881 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019882 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019883 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019884 }
19885 if(not $DepSymbols)
19886 { # Cannot reconstruct DepSymbols. This may result in false
19887 # positives if the old dump is for library 2. Not a problem if
19888 # old dumps are only from old libraries.
19889 $DepSymbols = {};
19890 }
19891 foreach my $Symbol (keys(%{$DepSymbols})) {
19892 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
19893 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019894 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019895 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040019896
19897 if(my $V = $TargetVersion{$LibVersion}) {
19898 $Descriptor{$LibVersion}{"Version"} = $V;
19899 }
19900 else {
19901 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
19902 }
19903
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019904 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019905 if(not $SkipTypes{$LibVersion})
19906 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019907 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019908 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030019909
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019910 if(not $SkipSymbols{$LibVersion})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030019911 { # if not defined by -skip-symbols option
19912 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
19913 if(not $SkipSymbols{$LibVersion})
19914 { # support for old dumps
19915 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
19916 }
19917 if(not $SkipSymbols{$LibVersion})
19918 { # support for old dumps
19919 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
19920 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019921 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019922 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030019923
19924 if(not $TargetHeaders{$LibVersion})
19925 { # if not defined by -headers-list option
19926 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
19927 }
19928
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019929 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019930 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019931 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019932 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019933 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019934 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019935 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019936 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019937 if(not checkDump($LibVersion, "2.10.1")
19938 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019939 { # support for old ABI dumps: added target headers
19940 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040019941 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019942 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019943 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040019944 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019945 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019946 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019947 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019948 if(defined $ABI->{"GccConstants"})
19949 { # 3.0
19950 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
19951 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
19952 }
19953 }
19954
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019955 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019956 if(not $NestedNameSpaces{$LibVersion})
19957 { # support for old dumps
19958 # Cannot reconstruct NameSpaces. This may affect design
19959 # of the compatibility report.
19960 $NestedNameSpaces{$LibVersion} = {};
19961 }
19962 # target system type
19963 # needed to adopt HTML report
19964 if(not $DumpSystem)
19965 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019966 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019967 }
19968 # recreate environment
19969 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
19970 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019971 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019972 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019973 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19974 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019975 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019976 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019977 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019978 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19979 {
19980 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19981 setLanguage($LibVersion, "C++");
19982 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019983 }
19984 }
19985 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019986 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
19987 {
19988 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
19989 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19990 }
19991 }
19992
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019993 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019994 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019995 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019996 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019997 {
19998 if(not $Symbol_Library{$LibVersion}{$MnglName}
19999 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20000 push(@VFunc, $MnglName);
20001 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020002 }
20003 }
20004 translateSymbols(@VFunc, $LibVersion);
20005 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020006 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20007
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020008 if(not checkDump($LibVersion, "3.0"))
20009 { # support for old ABI dumps
20010 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20011 {
20012 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20013 {
20014 if(ref($BaseType) eq "HASH") {
20015 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20016 }
20017 }
20018 }
20019 }
20020
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020021 if(not checkDump($LibVersion, "3.2"))
20022 { # support for old ABI dumps
20023 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20024 {
20025 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20026 {
20027 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20028 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20029 }
20030 }
20031 }
20032
20033 # repair target headers list
20034 delete($TargetHeaders{$LibVersion});
20035 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020036 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20037 }
20038 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20039 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020040 }
20041
20042 # non-target constants from anon enums
20043 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20044 {
20045 if(not $ExtraDump
20046 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20047 {
20048 delete($Constants{$LibVersion}{$Name});
20049 }
20050 }
20051 }
20052
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020053 if(not checkDump($LibVersion, "2.20"))
20054 { # support for old ABI dumps
20055 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20056 {
20057 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20058
20059 if($TType=~/Struct|Union|Enum|Typedef/)
20060 { # repair complex types first
20061 next;
20062 }
20063
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020064 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020065 {
20066 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20067 if($BType=~/Struct|Union|Enum/i)
20068 {
20069 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20070 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20071 }
20072 }
20073 }
20074 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20075 {
20076 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20077 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20078 if($TType=~/Struct|Union|Enum/) {
20079 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20080 }
20081 }
20082 }
20083
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020084 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020085 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020086 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20087 { # support for old ABI dumps < 2.0 (ACC 1.22)
20088 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20089 {
20090 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20091 {
20092 if($Access ne "public") {
20093 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20094 }
20095 }
20096 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20097 }
20098 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20099 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020100 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20101 { # support for old ABI dumps
20102 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20103 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020104 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20105 { # DWARF ABI Dumps
20106 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20107 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020108 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20109 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20110 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020111 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20112 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020113 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020114 foreach (keys(%{$TInfo{"Base"}})) {
20115 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020116 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020117 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020118 if($TInfo{"Type"} eq "MethodPtr")
20119 {
20120 if(defined $TInfo{"Param"})
20121 { # support for old ABI dumps <= 1.17
20122 if(not defined $TInfo{"Param"}{"0"})
20123 {
20124 my $Max = keys(%{$TInfo{"Param"}});
20125 foreach my $Pos (1 .. $Max) {
20126 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20127 }
20128 delete($TInfo{"Param"}{$Max});
20129 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20130 }
20131 }
20132 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020133 if($TInfo{"BaseType"} eq $TypeId)
20134 { # fix ABI dump
20135 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20136 }
20137 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020138 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020139 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020140 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020141 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20142 if(not $BName)
20143 { # broken type
20144 next;
20145 }
20146 if($TInfo{"Name"} eq $BName)
20147 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020148 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020149 next;
20150 }
20151 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20152 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020153 }
20154 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020155 }
20156 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20157 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020158 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020159 }
20160 }
20161
20162 if(not checkDump($LibVersion, "2.15"))
20163 { # support for old ABI dumps
20164 my %Dups = ();
20165 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20166 {
20167 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020168 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020169 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20170 { # remove template decls
20171 delete($SymbolInfo{$LibVersion}{$InfoId});
20172 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020173 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020174 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020175 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20176 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020177 { # templates
20178 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020179 }
20180 }
20181 }
20182
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020183 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20184 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020185 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20186 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20187 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20188 { # support for old ABI dumps (< 3.1)
20189 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20190 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20191 { # add "this" first parameter
20192 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20193 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20194
20195 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20196 {
20197 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20198 foreach my $Pos (reverse(0 .. $#Pos)) {
20199 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20200 }
20201 }
20202 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20203 }
20204 }
20205
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020206 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20207 { # ABI dumps have no mangled names for C-functions
20208 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20209 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020210 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20211 { # support for old ABI dumps
20212 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20213 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020214 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20215 { # DWARF ABI Dumps
20216 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20217 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020218 }
20219
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020220 $Descriptor{$LibVersion}{"Dump"} = 1;
20221}
20222
20223sub read_Machine_DumpInfo($$)
20224{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020225 my ($ABI, $LibVersion) = @_;
20226 if($ABI->{"Arch"}) {
20227 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020228 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020229 if($ABI->{"WordSize"}) {
20230 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020231 }
20232 else
20233 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020234 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020235 }
20236 if(not $WORD_SIZE{$LibVersion})
20237 { # support for old dumps (<1.23)
20238 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20239 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020240 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020241 }
20242 else
20243 {
20244 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020245 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020246 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020247 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20248 { # any "pointer"-type
20249 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020250 last;
20251 }
20252 }
20253 if($PSize)
20254 { # a pointer type size
20255 $WORD_SIZE{$LibVersion} = $PSize;
20256 }
20257 else {
20258 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20259 }
20260 }
20261 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020262 if($ABI->{"GccVersion"}) {
20263 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020264 }
20265}
20266
20267sub read_Libs_DumpInfo($$)
20268{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020269 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020270 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20271 if(not $Library_Symbol{$LibVersion})
20272 { # support for old dumps
20273 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20274 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020275 if(keys(%{$Library_Symbol{$LibVersion}})
20276 and not $DumpAPI) {
20277 $Descriptor{$LibVersion}{"Libs"} = "OK";
20278 }
20279}
20280
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020281sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020282{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020283 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020284
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020285 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020286 and not $DumpAPI) {
20287 $Descriptor{$LibVersion}{"Headers"} = "OK";
20288 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020289 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020290 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020291 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020292 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020293 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020294
20295 if(keys(%{$ABI->{"Sources"}})
20296 and not $DumpAPI) {
20297 $Descriptor{$LibVersion}{"Sources"} = "OK";
20298 }
20299 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020300 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020301 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20302 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20303 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020304}
20305
20306sub find_libs($$$)
20307{
20308 my ($Path, $Type, $MaxDepth) = @_;
20309 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020310 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020311}
20312
20313sub createDescriptor($$)
20314{
20315 my ($LibVersion, $Path) = @_;
20316 if(not $LibVersion or not $Path
20317 or not -e $Path) {
20318 return "";
20319 }
20320 if(-d $Path)
20321 { # directory with headers files and shared objects
20322 return "
20323 <version>
20324 ".$TargetVersion{$LibVersion}."
20325 </version>
20326
20327 <headers>
20328 $Path
20329 </headers>
20330
20331 <libs>
20332 $Path
20333 </libs>";
20334 }
20335 else
20336 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020337 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020338 { # standard XML-descriptor
20339 return readFile($Path);
20340 }
20341 elsif(is_header($Path, 2, $LibVersion))
20342 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020343 $CheckHeadersOnly = 1;
20344
20345 if($LibVersion==1) {
20346 $TargetVersion{$LibVersion} = "X";
20347 }
20348
20349 if($LibVersion==2) {
20350 $TargetVersion{$LibVersion} = "Y";
20351 }
20352
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020353 return "
20354 <version>
20355 ".$TargetVersion{$LibVersion}."
20356 </version>
20357
20358 <headers>
20359 $Path
20360 </headers>
20361
20362 <libs>
20363 none
20364 </libs>";
20365 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020366 else
20367 { # standard XML-descriptor
20368 return readFile($Path);
20369 }
20370 }
20371}
20372
20373sub detect_lib_default_paths()
20374{
20375 my %LPaths = ();
20376 if($OSgroup eq "bsd")
20377 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020378 if(my $LdConfig = get_CmdPath("ldconfig"))
20379 {
20380 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20381 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020382 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20383 {
20384 my $Name = "lib".$1;
20385 if(not defined $LPaths{$Name}) {
20386 $LPaths{$Name} = $2;
20387 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020388 }
20389 }
20390 }
20391 else {
20392 printMsg("WARNING", "can't find ldconfig");
20393 }
20394 }
20395 else
20396 {
20397 if(my $LdConfig = get_CmdPath("ldconfig"))
20398 {
20399 if($SystemRoot and $OSgroup eq "linux")
20400 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20401 if(-e $SystemRoot."/etc/ld.so.conf") {
20402 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20403 }
20404 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020405 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20406 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020407 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20408 {
20409 my ($Name, $Path) = ($1, $2);
20410 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020411 if(not defined $LPaths{$Name})
20412 { # get first element from the list of available paths
20413
20414 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20415 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20416 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20417
20418 $LPaths{$Name} = $Path;
20419 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020420 }
20421 }
20422 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020423 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020424 printMsg("WARNING", "can't find ldconfig");
20425 }
20426 }
20427 return \%LPaths;
20428}
20429
20430sub detect_bin_default_paths()
20431{
20432 my $EnvPaths = $ENV{"PATH"};
20433 if($OSgroup eq "beos") {
20434 $EnvPaths.=":".$ENV{"BETOOLS"};
20435 }
20436 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020437 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020438 {
20439 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020440 next if(not $Path);
20441 if($SystemRoot
20442 and $Path=~/\A\Q$SystemRoot\E\//)
20443 { # do NOT use binaries from target system
20444 next;
20445 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020446 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020447 }
20448}
20449
20450sub detect_inc_default_paths()
20451{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020452 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020453 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020454 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020455 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020456 next if(index($Line, "/cc1plus ")!=-1);
20457
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020458 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20459 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020460 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020461 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020462 if(index($Path, "c++")!=-1
20463 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020464 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020465 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020466 if(not defined $MAIN_CPP_DIR
20467 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20468 $MAIN_CPP_DIR = $Path;
20469 }
20470 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020471 elsif(index($Path, "gcc")!=-1) {
20472 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020473 }
20474 else
20475 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020476 if($Path=~/local[\/\\]+include/)
20477 { # local paths
20478 next;
20479 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020480 if($SystemRoot
20481 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20482 { # The GCC include path for user headers is not a part of the system root
20483 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20484 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20485 next;
20486 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020487 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020488 }
20489 }
20490 }
20491 unlink("$TMP_DIR/empty.h");
20492 return %DPaths;
20493}
20494
20495sub detect_default_paths($)
20496{
20497 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20498 my $Search = $_[0];
20499 if($Search!~/inc/) {
20500 $HSearch = 0;
20501 }
20502 if($Search!~/lib/) {
20503 $LSearch = 0;
20504 }
20505 if($Search!~/bin/) {
20506 $BSearch = 0;
20507 }
20508 if($Search!~/gcc/) {
20509 $GSearch = 0;
20510 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020511 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020512 { # <search_headers> section of the XML descriptor
20513 # do NOT search for systems headers
20514 $HSearch = 0;
20515 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020516 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030020517 { # <search_libs> section of the XML descriptor
20518 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020519 $LSearch = 0;
20520 }
20521 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20522 { # additional search paths
20523 next if($Type eq "include" and not $HSearch);
20524 next if($Type eq "lib" and not $LSearch);
20525 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020526 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020527 }
20528 if($OSgroup ne "windows")
20529 { # unix-like
20530 foreach my $Type ("include", "lib", "bin")
20531 { # automatic detection of system "devel" directories
20532 next if($Type eq "include" and not $HSearch);
20533 next if($Type eq "lib" and not $LSearch);
20534 next if($Type eq "bin" and not $BSearch);
20535 my ($UsrDir, $RootDir) = ("/usr", "/");
20536 if($SystemRoot and $Type ne "bin")
20537 { # 1. search for target headers and libraries
20538 # 2. use host commands: ldconfig, readelf, etc.
20539 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20540 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020541 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020542 if(-d $RootDir."/".$Type)
20543 { # if "/lib" is symbolic link
20544 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020545 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020546 }
20547 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020548 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020549 }
20550 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020551 if(-d $UsrDir)
20552 {
20553 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020554 if(-d $UsrDir."/".$Type)
20555 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020556 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020557 }
20558 }
20559 }
20560 }
20561 if($BSearch)
20562 {
20563 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020564 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020565 }
20566 # check environment variables
20567 if($OSgroup eq "beos")
20568 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020569 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020570 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020571 if($_ eq ".") {
20572 next;
20573 }
20574 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20575 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20576 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020577 }
20578 }
20579 if($HSearch)
20580 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020581 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20582 split(/:|;/, $ENV{"BEINCLUDES"})
20583 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020584 }
20585 if($LSearch)
20586 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020587 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20588 split(/:|;/, $ENV{"BELIBRARIES"}),
20589 split(/:|;/, $ENV{"LIBRARY_PATH"})
20590 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020591 }
20592 }
20593 if($LSearch)
20594 { # using linker to get system paths
20595 if(my $LPaths = detect_lib_default_paths())
20596 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020597 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020598 foreach my $Name (keys(%{$LPaths}))
20599 {
20600 if($SystemRoot
20601 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20602 { # wrong ldconfig configuration
20603 # check your <sysroot>/etc/ld.so.conf
20604 next;
20605 }
20606 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020607 if(my $Dir = get_dirname($LPaths->{$Name})) {
20608 $Dirs{$Dir} = 1;
20609 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020610 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020611 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020612 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020613 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020614 }
20615 if($BSearch)
20616 {
20617 if($CrossGcc)
20618 { # --cross-gcc=arm-linux-gcc
20619 if(-e $CrossGcc)
20620 { # absolute or relative path
20621 $GCC_PATH = get_abs_path($CrossGcc);
20622 }
20623 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20624 { # command name
20625 $GCC_PATH = $CrossGcc;
20626 }
20627 else {
20628 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20629 }
20630 if($GCC_PATH=~/\s/) {
20631 $GCC_PATH = "\"".$GCC_PATH."\"";
20632 }
20633 }
20634 }
20635 if($GSearch)
20636 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020637 if(not $CrossGcc)
20638 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020639 $GCC_PATH = get_CmdPath("gcc");
20640 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020641 if(not $GCC_PATH)
20642 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020643 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020644 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020645 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020646 { # select the latest version
20647 @GCCs = sort {$b cmp $a} @GCCs;
20648 if(check_gcc($GCCs[0], "3"))
20649 {
20650 $GCC_PATH = $GCCs[0];
20651 last;
20652 }
20653 }
20654 }
20655 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020656 if(not $GCC_PATH) {
20657 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
20658 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020659
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020660 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020661 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020662 my $GccTarget = get_dumpmachine($GCC_PATH);
20663
20664 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020665 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020666 $OStarget = "linux";
20667 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020668 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020669 elsif($GccTarget=~/symbian/)
20670 {
20671 $OStarget = "symbian";
20672 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
20673 }
20674
20675 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
20676
20677 # check GCC version
20678 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
20679 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
20680 # introduced in 4.8
20681 # fixed in 4.8.3
20682 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update or downgrade GCC or use a local installation by --gcc-path=PATH option.");
20683 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020684 }
20685 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020686 else {
20687 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020688 }
20689 }
20690 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020691 {
20692 # GCC standard paths
20693 if($GCC_PATH and not $NoStdInc)
20694 {
20695 my %DPaths = detect_inc_default_paths();
20696 @DefaultCppPaths = @{$DPaths{"Cpp"}};
20697 @DefaultGccPaths = @{$DPaths{"Gcc"}};
20698 @DefaultIncPaths = @{$DPaths{"Inc"}};
20699 push_U($SystemPaths{"include"}, @DefaultIncPaths);
20700 }
20701
20702 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020703 my $IncPath = "/usr/include";
20704 if($SystemRoot) {
20705 $IncPath = $SystemRoot.$IncPath;
20706 }
20707 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020708 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020709 }
20710 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020711
20712 if($ExtraInfo)
20713 {
20714 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
20715 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
20716 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020717}
20718
20719sub getLIB_EXT($)
20720{
20721 my $Target = $_[0];
20722 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
20723 return $Ext;
20724 }
20725 return $OS_LibExt{$LIB_TYPE}{"default"};
20726}
20727
20728sub getAR_EXT($)
20729{
20730 my $Target = $_[0];
20731 if(my $Ext = $OS_Archive{$Target}) {
20732 return $Ext;
20733 }
20734 return $OS_Archive{"default"};
20735}
20736
20737sub get_dumpversion($)
20738{
20739 my $Cmd = $_[0];
20740 return "" if(not $Cmd);
20741 if($Cache{"get_dumpversion"}{$Cmd}) {
20742 return $Cache{"get_dumpversion"}{$Cmd};
20743 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020744 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020745 chomp($V);
20746 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
20747}
20748
20749sub get_dumpmachine($)
20750{
20751 my $Cmd = $_[0];
20752 return "" if(not $Cmd);
20753 if($Cache{"get_dumpmachine"}{$Cmd}) {
20754 return $Cache{"get_dumpmachine"}{$Cmd};
20755 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020756 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020757 chomp($Machine);
20758 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
20759}
20760
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020761sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020762{
20763 my $Cmd = $_[0];
20764 return "" if(not $Cmd);
20765 my @Options = (
20766 "--version",
20767 "-help"
20768 );
20769 foreach my $Opt (@Options)
20770 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020771 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020772 if($Info) {
20773 return 1;
20774 }
20775 }
20776 return 0;
20777}
20778
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020779sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020780{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020781 my ($Cmd, $ReqVer) = @_;
20782 return 0 if(not $Cmd or not $ReqVer);
20783 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
20784 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020785 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020786 if(my $GccVer = get_dumpversion($Cmd))
20787 {
20788 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
20789 if(cmpVersions($GccVer, $ReqVer)>=0) {
20790 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
20791 }
20792 }
20793 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020794}
20795
20796sub get_depth($)
20797{
20798 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020799 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020800 }
20801 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
20802}
20803
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020804sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020805{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020806 return if($Cache{"registerGccHeaders"}); # this function should be called once
20807
20808 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020809 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020810 my @Headers = cmd_find($Path,"f");
20811 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20812 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020813 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020814 my $FileName = get_filename($HPath);
20815 if(not defined $DefaultGccHeader{$FileName})
20816 { # skip duplicated
20817 $DefaultGccHeader{$FileName} = $HPath;
20818 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020819 }
20820 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020821 $Cache{"registerGccHeaders"} = 1;
20822}
20823
20824sub registerCppHeaders()
20825{
20826 return if($Cache{"registerCppHeaders"}); # this function should be called once
20827
20828 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020829 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020830 my @Headers = cmd_find($CppDir,"f");
20831 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20832 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020833 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020834 my $FileName = get_filename($Path);
20835 if(not defined $DefaultCppHeader{$FileName})
20836 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020837 $DefaultCppHeader{$FileName} = $Path;
20838 }
20839 }
20840 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020841 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020842}
20843
20844sub parse_libname($$$)
20845{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020846 return "" if(not $_[0]);
20847 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
20848 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020849 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020850 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
20851}
20852
20853sub parse_libname_I($$$)
20854{
20855 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020856
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020857 if($Target eq "symbian") {
20858 return parse_libname_symbian($Name, $Type);
20859 }
20860 elsif($Target eq "windows") {
20861 return parse_libname_windows($Name, $Type);
20862 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020863
20864 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020865 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020866 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020867 { # libSDL-1.2.so.0.7.1
20868 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020869 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020870 if($Type eq "name")
20871 { # libSDL-1.2
20872 # libwbxml2
20873 return $2;
20874 }
20875 elsif($Type eq "name+ext")
20876 { # libSDL-1.2.so
20877 # libwbxml2.so
20878 return $1;
20879 }
20880 elsif($Type eq "version")
20881 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020882 if(defined $7
20883 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020884 { # 0.7.1
20885 return $7;
20886 }
20887 else
20888 { # libc-2.5.so (=>2.5 version)
20889 my $MV = $5;
20890 $MV=~s/\A[\-\_]+//g;
20891 return $MV;
20892 }
20893 }
20894 elsif($Type eq "short")
20895 { # libSDL
20896 # libwbxml2
20897 return $3;
20898 }
20899 elsif($Type eq "shortest")
20900 { # SDL
20901 # wbxml
20902 return shortest_name($3);
20903 }
20904 }
20905 return "";# error
20906}
20907
20908sub parse_libname_symbian($$)
20909{
20910 my ($Name, $Type) = @_;
20911 my $Ext = getLIB_EXT("symbian");
20912 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
20913 { # libpthread{00010001}.dso
20914 if($Type eq "name")
20915 { # libpthread{00010001}
20916 return $2;
20917 }
20918 elsif($Type eq "name+ext")
20919 { # libpthread{00010001}.dso
20920 return $1;
20921 }
20922 elsif($Type eq "version")
20923 { # 00010001
20924 my $V = $4;
20925 $V=~s/\{(.+)\}/$1/;
20926 return $V;
20927 }
20928 elsif($Type eq "short")
20929 { # libpthread
20930 return $3;
20931 }
20932 elsif($Type eq "shortest")
20933 { # pthread
20934 return shortest_name($3);
20935 }
20936 }
20937 return "";# error
20938}
20939
20940sub parse_libname_windows($$)
20941{
20942 my ($Name, $Type) = @_;
20943 my $Ext = getLIB_EXT("windows");
20944 if($Name=~/((.+?)\.$Ext)\Z/)
20945 { # netapi32.dll
20946 if($Type eq "name")
20947 { # netapi32
20948 return $2;
20949 }
20950 elsif($Type eq "name+ext")
20951 { # netapi32.dll
20952 return $1;
20953 }
20954 elsif($Type eq "version")
20955 { # DLL version embedded
20956 # at binary-level
20957 return "";
20958 }
20959 elsif($Type eq "short")
20960 { # netapi32
20961 return $2;
20962 }
20963 elsif($Type eq "shortest")
20964 { # netapi
20965 return shortest_name($2);
20966 }
20967 }
20968 return "";# error
20969}
20970
20971sub shortest_name($)
20972{
20973 my $Name = $_[0];
20974 # remove prefix
20975 $Name=~s/\A(lib|open)//;
20976 # remove suffix
20977 $Name=~s/[\W\d_]+\Z//i;
20978 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
20979 return $Name;
20980}
20981
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020982sub createSymbolsList($$$$$)
20983{
20984 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020985
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020986 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020987 prepareSymbols(1);
20988
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020989 my %SymbolHeaderLib = ();
20990 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020991
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020992 # Get List
20993 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
20994 {
20995 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020996 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020997 next;
20998 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020999 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021000 { # skip other symbols
21001 next;
21002 }
21003 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21004 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021005 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021006 next;
21007 }
21008 my $DyLib = $Symbol_Library{1}{$Symbol};
21009 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021010 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021011 next;
21012 }
21013 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21014 $Total+=1;
21015 }
21016 # Draw List
21017 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21018 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21019 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21020 {
21021 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21022 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021023 my %NS_Symbol = ();
21024 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021025 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021026 }
21027 foreach my $NameSpace (sort keys(%NS_Symbol))
21028 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021029 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021030 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21031 foreach my $Symbol (@SortedInterfaces)
21032 {
21033 my $SubReport = "";
21034 my $Signature = get_Signature($Symbol, 1);
21035 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021036 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021037 }
21038 if($Symbol=~/\A(_Z|\?)/)
21039 {
21040 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021041 $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 +040021042 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021043 else {
21044 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21045 }
21046 }
21047 else
21048 {
21049 if($Signature) {
21050 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21051 }
21052 else {
21053 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21054 }
21055 }
21056 $SYMBOLS_LIST .= $SubReport;
21057 }
21058 }
21059 $SYMBOLS_LIST .= "<br/>\n";
21060 }
21061 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021062 # clear info
21063 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21064 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21065 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21066 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021067 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021068 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021069 my $CssStyles = readModule("Styles", "SymbolsList.css");
21070 my $JScripts = readModule("Scripts", "Sections.js");
21071 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021072 my $Title = "$LName: public symbols";
21073 my $Keywords = "$LName, API, symbols";
21074 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021075 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021076 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030021077 <br/><br/><hr/>\n".getReportFooter("Single")."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021078 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021079 writeFile($SaveTo, $SYMBOLS_LIST);
21080}
21081
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021082sub add_target_libs($)
21083{
21084 foreach (@{$_[0]}) {
21085 $TargetLibs{$_} = 1;
21086 }
21087}
21088
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021089sub is_target_lib($)
21090{
21091 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021092 if(not $LName) {
21093 return 0;
21094 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021095 if($TargetLibraryName
21096 and $LName!~/\Q$TargetLibraryName\E/) {
21097 return 0;
21098 }
21099 if(keys(%TargetLibs)
21100 and not $TargetLibs{$LName}
21101 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21102 return 0;
21103 }
21104 return 1;
21105}
21106
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021107sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021108{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021109 my ($H, $V) = @_;
21110 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021111 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021112 if($TargetHeaders{$V}{$H}) {
21113 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021114 }
21115 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021116 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021117}
21118
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021119sub readLibs($)
21120{
21121 my $LibVersion = $_[0];
21122 if($OStarget eq "windows")
21123 { # dumpbin.exe will crash
21124 # without VS Environment
21125 check_win32_env();
21126 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021127 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021128 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021129 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021130}
21131
21132sub dump_sorting($)
21133{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021134 my $Hash = $_[0];
21135 return [] if(not $Hash);
21136 my @Keys = keys(%{$Hash});
21137 return [] if($#Keys<0);
21138 if($Keys[0]=~/\A\d+\Z/)
21139 { # numbers
21140 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021141 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021142 else
21143 { # strings
21144 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021145 }
21146}
21147
21148sub printMsg($$)
21149{
21150 my ($Type, $Msg) = @_;
21151 if($Type!~/\AINFO/) {
21152 $Msg = $Type.": ".$Msg;
21153 }
21154 if($Type!~/_C\Z/) {
21155 $Msg .= "\n";
21156 }
21157 if($Quiet)
21158 { # --quiet option
21159 appendFile($COMMON_LOG_PATH, $Msg);
21160 }
21161 else
21162 {
21163 if($Type eq "ERROR") {
21164 print STDERR $Msg;
21165 }
21166 else {
21167 print $Msg;
21168 }
21169 }
21170}
21171
21172sub exitStatus($$)
21173{
21174 my ($Code, $Msg) = @_;
21175 printMsg("ERROR", $Msg);
21176 exit($ERROR_CODE{$Code});
21177}
21178
21179sub exitReport()
21180{ # the tool has run without any errors
21181 printReport();
21182 if($COMPILE_ERRORS)
21183 { # errors in headers may add false positives/negatives
21184 exit($ERROR_CODE{"Compile_Error"});
21185 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021186 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21187 { # --binary
21188 exit($ERROR_CODE{"Incompatible"});
21189 }
21190 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21191 { # --source
21192 exit($ERROR_CODE{"Incompatible"});
21193 }
21194 elsif($RESULT{"Source"}{"Problems"}
21195 or $RESULT{"Binary"}{"Problems"})
21196 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021197 exit($ERROR_CODE{"Incompatible"});
21198 }
21199 else {
21200 exit($ERROR_CODE{"Compatible"});
21201 }
21202}
21203
21204sub readRules($)
21205{
21206 my $Kind = $_[0];
21207 if(not -f $RULES_PATH{$Kind}) {
21208 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21209 }
21210 my $Content = readFile($RULES_PATH{$Kind});
21211 while(my $Rule = parseTag(\$Content, "rule"))
21212 {
21213 my $RId = parseTag(\$Rule, "id");
21214 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21215 foreach my $Prop (@Properties) {
21216 if(my $Value = parseTag(\$Rule, lc($Prop)))
21217 {
21218 $Value=~s/\n[ ]*//;
21219 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21220 }
21221 }
21222 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21223 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21224 }
21225 else {
21226 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21227 }
21228 }
21229}
21230
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021231sub getReportPath($)
21232{
21233 my $Level = $_[0];
21234 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21235 if($Level eq "Binary")
21236 {
21237 if($BinaryReportPath)
21238 { # --bin-report-path
21239 return $BinaryReportPath;
21240 }
21241 elsif($OutputReportPath)
21242 { # --report-path
21243 return $OutputReportPath;
21244 }
21245 else
21246 { # default
21247 return $Dir."/abi_compat_report.$ReportFormat";
21248 }
21249 }
21250 elsif($Level eq "Source")
21251 {
21252 if($SourceReportPath)
21253 { # --src-report-path
21254 return $SourceReportPath;
21255 }
21256 elsif($OutputReportPath)
21257 { # --report-path
21258 return $OutputReportPath;
21259 }
21260 else
21261 { # default
21262 return $Dir."/src_compat_report.$ReportFormat";
21263 }
21264 }
21265 else
21266 {
21267 if($OutputReportPath)
21268 { # --report-path
21269 return $OutputReportPath;
21270 }
21271 else
21272 { # default
21273 return $Dir."/compat_report.$ReportFormat";
21274 }
21275 }
21276}
21277
21278sub printStatMsg($)
21279{
21280 my $Level = $_[0];
21281 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21282}
21283
21284sub listAffected($)
21285{
21286 my $Level = $_[0];
21287 my $List = "";
21288 foreach (keys(%{$TotalAffected{$Level}}))
21289 {
21290 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21291 { # skip "Low"-severity problems
21292 next;
21293 }
21294 $List .= "$_\n";
21295 }
21296 my $Dir = get_dirname(getReportPath($Level));
21297 if($Level eq "Binary") {
21298 writeFile($Dir."/abi_affected.txt", $List);
21299 }
21300 elsif($Level eq "Source") {
21301 writeFile($Dir."/src_affected.txt", $List);
21302 }
21303}
21304
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021305sub printReport()
21306{
21307 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021308 createReport();
21309 if($JoinReport or $DoubleReport)
21310 {
21311 if($RESULT{"Binary"}{"Problems"}
21312 or $RESULT{"Source"}{"Problems"}) {
21313 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021314 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021315 else {
21316 printMsg("INFO", "result: COMPATIBLE");
21317 }
21318 printStatMsg("Binary");
21319 printStatMsg("Source");
21320 if($ListAffected)
21321 { # --list-affected
21322 listAffected("Binary");
21323 listAffected("Source");
21324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021325 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021326 elsif($BinaryOnly)
21327 {
21328 if($RESULT{"Binary"}{"Problems"}) {
21329 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21330 }
21331 else {
21332 printMsg("INFO", "result: COMPATIBLE");
21333 }
21334 printStatMsg("Binary");
21335 if($ListAffected)
21336 { # --list-affected
21337 listAffected("Binary");
21338 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021339 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021340 elsif($SourceOnly)
21341 {
21342 if($RESULT{"Source"}{"Problems"}) {
21343 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21344 }
21345 else {
21346 printMsg("INFO", "result: COMPATIBLE");
21347 }
21348 printStatMsg("Source");
21349 if($ListAffected)
21350 { # --list-affected
21351 listAffected("Source");
21352 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021353 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021354 if($StdOut)
21355 {
21356 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021357 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021358 printMsg("INFO", "compatibility report has been generated to stdout");
21359 }
21360 else
21361 { # default
21362 printMsg("INFO", "compatibility reports have been generated to stdout");
21363 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021364 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021365 else
21366 {
21367 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021368 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021369 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21370 }
21371 elsif($DoubleReport)
21372 { # default
21373 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21374 }
21375 elsif($BinaryOnly)
21376 { # --binary
21377 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21378 }
21379 elsif($SourceOnly)
21380 { # --source
21381 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21382 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021383 }
21384}
21385
21386sub check_win32_env()
21387{
21388 if(not $ENV{"DevEnvDir"}
21389 or not $ENV{"LIB"}) {
21390 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21391 }
21392}
21393
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021394sub diffSets($$)
21395{
21396 my ($S1, $S2) = @_;
21397 my @SK1 = keys(%{$S1});
21398 my @SK2 = keys(%{$S2});
21399 if($#SK1!=$#SK2) {
21400 return 1;
21401 }
21402 foreach my $K1 (@SK1)
21403 {
21404 if(not defined $S2->{$K1}) {
21405 return 1;
21406 }
21407 }
21408 return 0;
21409}
21410
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021411sub defaultDumpPath($$)
21412{
21413 my ($N, $V) = @_;
21414 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21415}
21416
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021417sub create_ABI_Dump()
21418{
21419 if(not -e $DumpAPI) {
21420 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21421 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021422
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021423 if(isDump($DumpAPI)) {
21424 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021425 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021426 else {
21427 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021428 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021429
21430 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021431 { # set to default: N
21432 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021433 }
21434
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021435 initLogging(1);
21436 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021437
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021438 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021439 if($OutputDumpPath)
21440 { # user defined path
21441 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021442 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021443 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21444
21445 if(not $Archive and not $StdOut)
21446 { # check archive utilities
21447 if($OSgroup eq "windows")
21448 { # using zip
21449 my $ZipCmd = get_CmdPath("zip");
21450 if(not $ZipCmd) {
21451 exitStatus("Not_Found", "can't find \"zip\"");
21452 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021453 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021454 else
21455 { # using tar and gzip
21456 my $TarCmd = get_CmdPath("tar");
21457 if(not $TarCmd) {
21458 exitStatus("Not_Found", "can't find \"tar\"");
21459 }
21460 my $GzipCmd = get_CmdPath("gzip");
21461 if(not $GzipCmd) {
21462 exitStatus("Not_Found", "can't find \"gzip\"");
21463 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021464 }
21465 }
21466
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021467 if(not $Descriptor{1}{"Dump"})
21468 {
21469 if(not $CheckHeadersOnly) {
21470 readLibs(1);
21471 }
21472 if($CheckHeadersOnly) {
21473 setLanguage(1, "C++");
21474 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021475 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021476 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021477 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021478 if(not $Descriptor{1}{"Dump"})
21479 {
21480 if($Descriptor{1}{"Headers"}) {
21481 readHeaders(1);
21482 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021483 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021484 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021485 if(not keys(%{$SymbolInfo{1}}))
21486 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021487 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021488 {
21489 if($CheckHeadersOnly) {
21490 exitStatus("Empty_Set", "the set of public symbols is empty");
21491 }
21492 else {
21493 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21494 }
21495 }
21496 }
21497 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021498 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021499 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21500 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021501 if($ExtraDump)
21502 { # add unmangled names to the ABI dump
21503 my @Names = ();
21504 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21505 {
21506 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21507 push(@Names, $MnglName);
21508 }
21509 }
21510 translateSymbols(@Names, 1);
21511 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21512 {
21513 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21514 {
21515 if(my $Unmangled = $tr_name{$MnglName})
21516 {
21517 if($MnglName ne $Unmangled) {
21518 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21519 }
21520 }
21521 }
21522 }
21523 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021524
21525 my %GccConstants = (); # built-in GCC constants
21526 foreach my $Name (keys(%{$Constants{1}}))
21527 {
21528 if(not defined $Constants{1}{$Name}{"Header"})
21529 {
21530 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21531 delete($Constants{1}{$Name});
21532 }
21533 }
21534
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021535 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021536 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021537 "TypeInfo" => $TypeInfo{1},
21538 "SymbolInfo" => $SymbolInfo{1},
21539 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021540 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021541 "SymbolVersion" => $SymVer{1},
21542 "LibraryVersion" => $Descriptor{1}{"Version"},
21543 "LibraryName" => $TargetLibraryName,
21544 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021545 "SkipTypes" => $SkipTypes{1},
21546 "SkipSymbols" => $SkipSymbols{1},
21547 "SkipNameSpaces" => $SkipNameSpaces{1},
21548 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021549 "Headers" => \%HeadersInfo,
21550 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021551 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021552 "NameSpaces" => $NestedNameSpaces{1},
21553 "Target" => $OStarget,
21554 "Arch" => getArch(1),
21555 "WordSize" => $WORD_SIZE{1},
21556 "GccVersion" => get_dumpversion($GCC_PATH),
21557 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21558 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21559 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021560 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021561 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021562 }
21563 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021564 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021565 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021566 if($ExtendedCheck)
21567 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021568 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021569 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021570 if($BinaryOnly)
21571 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021572 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021573 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021574 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021575 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021576 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021577 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21578 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021579 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021580
21581 my $ABI_DUMP = "";
21582 if($UseXML)
21583 {
21584 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021585 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021586 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021587 else
21588 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021589 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021590 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021591 if($StdOut)
21592 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021593 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021594 printMsg("INFO", "ABI dump has been generated to stdout");
21595 return;
21596 }
21597 else
21598 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021599 my ($DDir, $DName) = separate_path($DumpPath);
21600 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021601 if(not $Archive) {
21602 $DPath = $DumpPath;
21603 }
21604
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021605 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021606
21607 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021608 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021609 close(DUMP);
21610
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021611 if(not -s $DPath) {
21612 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21613 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021614 if($Archive) {
21615 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021616 }
21617
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021618 if($OutputDumpPath) {
21619 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021620 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021621 else {
21622 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
21623 }
21624 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 +040021625 }
21626}
21627
21628sub quickEmptyReports()
21629{ # Quick "empty" reports
21630 # 4 times faster than merging equal dumps
21631 # NOTE: the dump contains the "LibraryVersion" attribute
21632 # if you change the version, then your dump will be different
21633 # OVERCOME: use -v1 and v2 options for comparing dumps
21634 # and don't change version in the XML descriptor (and dumps)
21635 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
21636 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
21637 {
21638 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
21639 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
21640 if($FilePath1 and $FilePath2)
21641 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021642 my $Line = readLineNum($FilePath1, 0);
21643 if($Line=~/xml/)
21644 { # XML format
21645 # is not supported yet
21646 return;
21647 }
21648
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021649 local $/ = undef;
21650
21651 open(DUMP1, $FilePath1);
21652 my $Content1 = <DUMP1>;
21653 close(DUMP1);
21654
21655 open(DUMP2, $FilePath2);
21656 my $Content2 = <DUMP2>;
21657 close(DUMP2);
21658
21659 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021660 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021661 # clean memory
21662 undef $Content2;
21663
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021664 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021665 my $ABIdump = eval($Content1);
21666
21667 # clean memory
21668 undef $Content1;
21669
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021670 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021671 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 +040021672 }
21673 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021674 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021675 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
21676 }
21677 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021678 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021679 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
21680 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021681 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021682 read_Libs_DumpInfo($ABIdump, 1);
21683 read_Machine_DumpInfo($ABIdump, 1);
21684 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021685
21686 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
21687 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
21688
21689 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
21690 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
21691
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021692 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
21693 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
21694 exitReport();
21695 }
21696 }
21697 }
21698}
21699
21700sub initLogging($)
21701{
21702 my $LibVersion = $_[0];
21703 # create log directory
21704 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
21705 if($OutputLogPath{$LibVersion})
21706 { # user-defined by -log-path option
21707 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
21708 }
21709 if($LogMode ne "n") {
21710 mkpath($LOG_DIR);
21711 }
21712 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021713 if($Debug)
21714 { # debug directory
21715 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021716
21717 if(not $ExtraInfo)
21718 { # enable --extra-info
21719 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
21720 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021721 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021722 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021723}
21724
21725sub writeLog($$)
21726{
21727 my ($LibVersion, $Msg) = @_;
21728 if($LogMode ne "n") {
21729 appendFile($LOG_PATH{$LibVersion}, $Msg);
21730 }
21731}
21732
21733sub resetLogging($)
21734{
21735 my $LibVersion = $_[0];
21736 if($LogMode!~/a|n/)
21737 { # remove old log
21738 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021739 if($Debug) {
21740 rmtree($DEBUG_PATH{$LibVersion});
21741 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021742 }
21743}
21744
21745sub printErrorLog($)
21746{
21747 my $LibVersion = $_[0];
21748 if($LogMode ne "n") {
21749 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
21750 }
21751}
21752
21753sub isDump($)
21754{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021755 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
21756 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021757 return $1;
21758 }
21759 return 0;
21760}
21761
21762sub isDump_U($)
21763{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021764 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021765 return $1;
21766 }
21767 return 0;
21768}
21769
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021770sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021771{
21772 # read input XML descriptors or ABI dumps
21773 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021774 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021775 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021776 if(not -e $Descriptor{1}{"Path"}) {
21777 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021778 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021779
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021780 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021781 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021782 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021783 if(not -e $Descriptor{2}{"Path"}) {
21784 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021785 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021786
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021787 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021788 if(isDump($Descriptor{1}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021789 and isDump($Descriptor{2}{"Path"}))
21790 { # optimization: equal ABI dumps
21791 quickEmptyReports();
21792 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021793
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021794 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021795
21796 if(isDump($Descriptor{1}{"Path"})) {
21797 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021798 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021799 else {
21800 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
21801 }
21802
21803 if(isDump($Descriptor{2}{"Path"})) {
21804 read_ABI_Dump(2, $Descriptor{2}{"Path"});
21805 }
21806 else {
21807 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021808 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021809
21810 if(not $Descriptor{1}{"Version"})
21811 { # set to default: X
21812 $Descriptor{1}{"Version"} = "X";
21813 }
21814
21815 if(not $Descriptor{2}{"Version"})
21816 { # set to default: Y
21817 $Descriptor{2}{"Version"} = "Y";
21818 }
21819
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021820 initLogging(1);
21821 initLogging(2);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021822
21823 # check input data
21824 if(not $Descriptor{1}{"Headers"}) {
21825 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021826 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021827 if(not $Descriptor{2}{"Headers"}) {
21828 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021829 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021830
21831 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021832 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021833 if(not $Descriptor{1}{"Libs"}) {
21834 exitStatus("Error", "can't find libraries info in descriptor d1");
21835 }
21836 if(not $Descriptor{2}{"Libs"}) {
21837 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021838 }
21839 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021840
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021841 if($UseDumps)
21842 { # --use-dumps
21843 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021844 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
21845 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021846
21847 unlink($DumpPath1);
21848 unlink($DumpPath2);
21849
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021850 my $pid = fork();
21851 if($pid)
21852 { # dump on two CPU cores
21853 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
21854 if($RelativeDirectory{1}) {
21855 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
21856 }
21857 if($OutputLogPath{1}) {
21858 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
21859 }
21860 if($CrossGcc) {
21861 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
21862 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021863 if($Quiet)
21864 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021865 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021866 @PARAMS = (@PARAMS, "-logging-mode", "a");
21867 }
21868 elsif($LogMode and $LogMode ne "w")
21869 { # "w" is default
21870 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021871 }
21872 if($ExtendedCheck) {
21873 @PARAMS = (@PARAMS, "-extended");
21874 }
21875 if($UserLang) {
21876 @PARAMS = (@PARAMS, "-lang", $UserLang);
21877 }
21878 if($TargetVersion{1}) {
21879 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
21880 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021881 if($BinaryOnly) {
21882 @PARAMS = (@PARAMS, "-binary");
21883 }
21884 if($SourceOnly) {
21885 @PARAMS = (@PARAMS, "-source");
21886 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021887 if($SortDump) {
21888 @PARAMS = (@PARAMS, "-sort");
21889 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021890 if($DumpFormat and $DumpFormat ne "perl") {
21891 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
21892 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021893 if($CheckHeadersOnly) {
21894 @PARAMS = (@PARAMS, "-headers-only");
21895 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021896 if($Debug)
21897 {
21898 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021899 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021900 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021901 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021902 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021903 exit(1);
21904 }
21905 }
21906 else
21907 { # child
21908 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
21909 if($RelativeDirectory{2}) {
21910 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
21911 }
21912 if($OutputLogPath{2}) {
21913 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
21914 }
21915 if($CrossGcc) {
21916 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
21917 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021918 if($Quiet)
21919 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021920 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021921 @PARAMS = (@PARAMS, "-logging-mode", "a");
21922 }
21923 elsif($LogMode and $LogMode ne "w")
21924 { # "w" is default
21925 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021926 }
21927 if($ExtendedCheck) {
21928 @PARAMS = (@PARAMS, "-extended");
21929 }
21930 if($UserLang) {
21931 @PARAMS = (@PARAMS, "-lang", $UserLang);
21932 }
21933 if($TargetVersion{2}) {
21934 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
21935 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021936 if($BinaryOnly) {
21937 @PARAMS = (@PARAMS, "-binary");
21938 }
21939 if($SourceOnly) {
21940 @PARAMS = (@PARAMS, "-source");
21941 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021942 if($SortDump) {
21943 @PARAMS = (@PARAMS, "-sort");
21944 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021945 if($DumpFormat and $DumpFormat ne "perl") {
21946 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
21947 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021948 if($CheckHeadersOnly) {
21949 @PARAMS = (@PARAMS, "-headers-only");
21950 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021951 if($Debug)
21952 {
21953 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021954 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021955 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021956 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021957 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021958 exit(1);
21959 }
21960 else {
21961 exit(0);
21962 }
21963 }
21964 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030021965
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021966 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021967 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
21968 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030021969 if($TargetTitle ne $TargetLibraryName) {
21970 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021971 }
21972 if($ShowRetVal) {
21973 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
21974 }
21975 if($CrossGcc) {
21976 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
21977 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021978 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
21979 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021980 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021981 }
21982 if($ReportFormat and $ReportFormat ne "html")
21983 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021984 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
21985 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021986 if($OutputReportPath) {
21987 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
21988 }
21989 if($BinaryReportPath) {
21990 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
21991 }
21992 if($SourceReportPath) {
21993 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
21994 }
21995 if($LoggingPath) {
21996 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
21997 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021998 if($CheckHeadersOnly) {
21999 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22000 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022001 if($BinaryOnly) {
22002 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22003 }
22004 if($SourceOnly) {
22005 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22006 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022007 if($Debug)
22008 {
22009 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22010 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022011 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022012 system("perl", $0, @CMP_PARAMS);
22013 exit($?>>8);
22014 }
22015 if(not $Descriptor{1}{"Dump"}
22016 or not $Descriptor{2}{"Dump"})
22017 { # need GCC toolchain to analyze
22018 # header files and libraries
22019 detect_default_paths("inc|lib|gcc");
22020 }
22021 if(not $Descriptor{1}{"Dump"})
22022 {
22023 if(not $CheckHeadersOnly) {
22024 readLibs(1);
22025 }
22026 if($CheckHeadersOnly) {
22027 setLanguage(1, "C++");
22028 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022029 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022030 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022031 }
22032 if(not $Descriptor{2}{"Dump"})
22033 {
22034 if(not $CheckHeadersOnly) {
22035 readLibs(2);
22036 }
22037 if($CheckHeadersOnly) {
22038 setLanguage(2, "C++");
22039 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022040 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022041 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022042 }
22043 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22044 { # support for old ABI dumps
22045 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022046 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022047 {
22048 $WORD_SIZE{1} = $WORD_SIZE{2};
22049 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22050 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022051 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022052 {
22053 $WORD_SIZE{2} = $WORD_SIZE{1};
22054 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22055 }
22056 }
22057 elsif(not $WORD_SIZE{1}
22058 and not $WORD_SIZE{2})
22059 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022060 $WORD_SIZE{1} = "4";
22061 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022062 }
22063 if($Descriptor{1}{"Dump"})
22064 { # support for old ABI dumps
22065 prepareTypes(1);
22066 }
22067 if($Descriptor{2}{"Dump"})
22068 { # support for old ABI dumps
22069 prepareTypes(2);
22070 }
22071 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22072 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22073 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022074 # process input data
22075 if($Descriptor{1}{"Headers"}
22076 and not $Descriptor{1}{"Dump"}) {
22077 readHeaders(1);
22078 }
22079 if($Descriptor{2}{"Headers"}
22080 and not $Descriptor{2}{"Dump"}) {
22081 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022082 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022083
22084 # clean memory
22085 %SystemHeaders = ();
22086 %mangled_name_gcc = ();
22087
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022088 prepareSymbols(1);
22089 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022090
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022091 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022092 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022093
22094 # Virtual Tables
22095 registerVTable(1);
22096 registerVTable(2);
22097
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022098 if(not checkDump(1, "1.22")
22099 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022100 { # support for old ABI dumps
22101 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22102 {
22103 if($ClassName=~/</)
22104 { # templates
22105 if(not defined $VirtualTable{1}{$ClassName})
22106 { # synchronize
22107 delete($VirtualTable{2}{$ClassName});
22108 }
22109 }
22110 }
22111 }
22112
22113 registerOverriding(1);
22114 registerOverriding(2);
22115
22116 setVirtFuncPositions(1);
22117 setVirtFuncPositions(2);
22118
22119 # Other
22120 addParamNames(1);
22121 addParamNames(2);
22122
22123 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022124}
22125
22126sub compareAPIs($)
22127{
22128 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022129
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022130 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022131 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022132
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022133 if($Level eq "Binary") {
22134 printMsg("INFO", "comparing ABIs ...");
22135 }
22136 else {
22137 printMsg("INFO", "comparing APIs ...");
22138 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022139
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022140 if($CheckHeadersOnly
22141 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022142 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022143 detectAdded_H($Level);
22144 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022145 }
22146 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022147 { # added/removed in libs
22148 detectAdded($Level);
22149 detectRemoved($Level);
22150 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022151
22152 mergeSymbols($Level);
22153 if(keys(%{$CheckedSymbols{$Level}})) {
22154 mergeConstants($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022155 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022156
22157 $Cache{"mergeTypes"} = (); # free memory
22158
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022159 if($CheckHeadersOnly
22160 or $Level eq "Source")
22161 { # added/removed in headers
22162 mergeHeaders($Level);
22163 }
22164 else
22165 { # added/removed in libs
22166 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022167 }
22168}
22169
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022170sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022171{
22172 my %Opts = (
22173 "OStarget"=>$OStarget,
22174 "Debug"=>$Debug,
22175 "Quiet"=>$Quiet,
22176 "LogMode"=>$LogMode,
22177 "CheckHeadersOnly"=>$CheckHeadersOnly,
22178
22179 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022180 "GCC_PATH"=>$GCC_PATH,
22181 "TargetSysInfo"=>$TargetSysInfo,
22182 "CrossPrefix"=>$CrossPrefix,
22183 "TargetLibraryName"=>$TargetLibraryName,
22184 "CrossGcc"=>$CrossGcc,
22185 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022186 "NoStdInc"=>$NoStdInc,
22187
22188 "BinaryOnly" => $BinaryOnly,
22189 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022190 );
22191 return \%Opts;
22192}
22193
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022194sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022195{
22196 my %CODE_ERROR = reverse(%ERROR_CODE);
22197 return $CODE_ERROR{$_[0]};
22198}
22199
22200sub scenario()
22201{
22202 if($StdOut)
22203 { # enable quiet mode
22204 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022205 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022206 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022207 if(not $LogMode)
22208 { # default
22209 $LogMode = "w";
22210 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022211 if($UserLang)
22212 { # --lang=C++
22213 $UserLang = uc($UserLang);
22214 $COMMON_LANGUAGE{1}=$UserLang;
22215 $COMMON_LANGUAGE{2}=$UserLang;
22216 }
22217 if($LoggingPath)
22218 {
22219 $OutputLogPath{1} = $LoggingPath;
22220 $OutputLogPath{2} = $LoggingPath;
22221 if($Quiet) {
22222 $COMMON_LOG_PATH = $LoggingPath;
22223 }
22224 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022225 if($Quick) {
22226 $ADD_TMPL_INSTANCES = 0;
22227 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022228 if($OutputDumpPath)
22229 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022230 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022231 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22232 }
22233 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022234 if($BinaryOnly and $SourceOnly)
22235 { # both --binary and --source
22236 # is the default mode
22237 $DoubleReport = 1;
22238 $JoinReport = 0;
22239 $BinaryOnly = 0;
22240 $SourceOnly = 0;
22241 if($OutputReportPath)
22242 { # --report-path
22243 $DoubleReport = 0;
22244 $JoinReport = 1;
22245 }
22246 }
22247 elsif($BinaryOnly or $SourceOnly)
22248 { # --binary or --source
22249 $DoubleReport = 0;
22250 $JoinReport = 0;
22251 }
22252 if($UseXML)
22253 { # --xml option
22254 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022255 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022256 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022257 if($ReportFormat)
22258 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022259 $ReportFormat = lc($ReportFormat);
22260 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022261 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022262 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022263 if($ReportFormat eq "htm")
22264 { # HTM == HTML
22265 $ReportFormat = "html";
22266 }
22267 elsif($ReportFormat eq "xml")
22268 { # --report-format=XML equal to --xml
22269 $UseXML = 1;
22270 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022271 }
22272 else
22273 { # default: HTML
22274 $ReportFormat = "html";
22275 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022276 if($DumpFormat)
22277 { # validate
22278 $DumpFormat = lc($DumpFormat);
22279 if($DumpFormat!~/\A(xml|perl)\Z/) {
22280 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22281 }
22282 if($DumpFormat eq "xml")
22283 { # --dump-format=XML equal to --xml
22284 $UseXML = 1;
22285 }
22286 }
22287 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022288 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022289 $DumpFormat = "perl";
22290 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022291 if($Quiet and $LogMode!~/a|n/)
22292 { # --quiet log
22293 if(-f $COMMON_LOG_PATH) {
22294 unlink($COMMON_LOG_PATH);
22295 }
22296 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022297 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022298 $CheckUndefined = 1;
22299 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022300 if($TestTool and $UseDumps)
22301 { # --test && --use-dumps == --test-dump
22302 $TestDump = 1;
22303 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022304 if($Tolerant)
22305 { # enable all
22306 $Tolerance = 1234;
22307 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022308 if($Help)
22309 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022310 HELP_MESSAGE();
22311 exit(0);
22312 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022313 if($InfoMsg)
22314 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022315 INFO_MESSAGE();
22316 exit(0);
22317 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022318 if($ShowVersion)
22319 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022320 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 +040022321 exit(0);
22322 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022323 if($DumpVersion)
22324 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022325 printMsg("INFO", $TOOL_VERSION);
22326 exit(0);
22327 }
22328 if($ExtendedCheck) {
22329 $CheckHeadersOnly = 1;
22330 }
22331 if($SystemRoot_Opt)
22332 { # user defined root
22333 if(not -e $SystemRoot_Opt) {
22334 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22335 }
22336 $SystemRoot = $SystemRoot_Opt;
22337 $SystemRoot=~s/[\/]+\Z//g;
22338 if($SystemRoot) {
22339 $SystemRoot = get_abs_path($SystemRoot);
22340 }
22341 }
22342 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022343
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022344 if($SortDump)
22345 {
22346 $Data::Dumper::Useperl = 1;
22347 $Data::Dumper::Sortkeys = \&dump_sorting;
22348 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022349
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022350 if($TargetLibsPath)
22351 {
22352 if(not -f $TargetLibsPath) {
22353 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22354 }
22355 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22356 $TargetLibs{$Lib} = 1;
22357 }
22358 }
22359 if($TargetHeadersPath)
22360 { # --headers-list
22361 if(not -f $TargetHeadersPath) {
22362 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22363 }
22364 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22365 {
22366 $TargetHeaders{1}{$Header} = 1;
22367 $TargetHeaders{2}{$Header} = 1;
22368 }
22369 }
22370 if($TargetHeader)
22371 { # --header
22372 $TargetHeaders{1}{$TargetHeader} = 1;
22373 $TargetHeaders{2}{$TargetHeader} = 1;
22374 }
22375 if($TestTool
22376 or $TestDump)
22377 { # --test, --test-dump
22378 detect_default_paths("bin|gcc"); # to compile libs
22379 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022380 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022381 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022382 exit(0);
22383 }
22384 if($DumpSystem)
22385 { # --dump-system
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022386
22387 if(not $TargetSysInfo) {
22388 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22389 }
22390
22391 if(not -d $TargetSysInfo) {
22392 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22393 }
22394
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022395 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022396 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022397 { # system XML descriptor
22398 if(not -f $DumpSystem) {
22399 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22400 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030022401
22402 my $SDesc = readFile($DumpSystem);
22403 if(my $RelDir = $RelativeDirectory{1}) {
22404 $SDesc =~ s/{RELPATH}/$RelDir/g;
22405 }
22406
22407 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022408 foreach (@{$Ret->{"Tools"}})
22409 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022410 push_U($SystemPaths{"bin"}, $_);
22411 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022412 }
22413 if($Ret->{"CrossPrefix"}) {
22414 $CrossPrefix = $Ret->{"CrossPrefix"};
22415 }
22416 }
22417 elsif($SystemRoot_Opt)
22418 { # -sysroot "/" option
22419 # default target: /usr/lib, /usr/include
22420 # search libs: /usr/lib and /lib
22421 if(not -e $SystemRoot."/usr/lib") {
22422 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22423 }
22424 if(not -e $SystemRoot."/lib") {
22425 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22426 }
22427 if(not -e $SystemRoot."/usr/include") {
22428 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22429 }
22430 readSystemDescriptor("
22431 <name>
22432 $DumpSystem
22433 </name>
22434 <headers>
22435 $SystemRoot/usr/include
22436 </headers>
22437 <libs>
22438 $SystemRoot/usr/lib
22439 </libs>
22440 <search_libs>
22441 $SystemRoot/lib
22442 </search_libs>");
22443 }
22444 else {
22445 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22446 }
22447 detect_default_paths("bin|gcc"); # to check symbols
22448 if($OStarget eq "windows")
22449 { # to run dumpbin.exe
22450 # and undname.exe
22451 check_win32_env();
22452 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022453 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022454 exit(0);
22455 }
22456 if($CmpSystems)
22457 { # --cmp-systems
22458 detect_default_paths("bin"); # to extract dumps
22459 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022460 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022461 exit(0);
22462 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022463 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022464 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022465 }
22466 else
22467 { # validate library name
22468 if($TargetLibraryName=~/[\*\/\\]/) {
22469 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22470 }
22471 }
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022472 if(not $TargetTitle) {
22473 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022474 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022475
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022476 if($SymbolsListPath)
22477 {
22478 if(not -f $SymbolsListPath) {
22479 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22480 }
22481 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22482 $SymbolsList{$Interface} = 1;
22483 }
22484 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022485 if($TypesListPath)
22486 {
22487 if(not -f $TypesListPath) {
22488 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
22489 }
22490 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
22491 $TypesList{$Type} = 1;
22492 }
22493 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022494 if($SkipSymbolsListPath)
22495 {
22496 if(not -f $SkipSymbolsListPath) {
22497 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22498 }
22499 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath))) {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022500 $SkipSymbols{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022501 }
22502 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022503 if($SkipHeadersPath)
22504 {
22505 if(not -f $SkipHeadersPath) {
22506 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22507 }
22508 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022509 { # register for both versions
22510 $SkipHeadersList{1}{$Path} = 1;
22511 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022512 my ($CPath, $Type) = classifyPath($Path);
22513 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022514 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022515 }
22516 }
22517 if($ParamNamesPath)
22518 {
22519 if(not -f $ParamNamesPath) {
22520 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22521 }
22522 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22523 {
22524 if($Line=~s/\A(\w+)\;//)
22525 {
22526 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022527 if($Line=~/;(\d+);/)
22528 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022529 while($Line=~s/(\d+);(\w+)//) {
22530 $AddIntParams{$Interface}{$1}=$2;
22531 }
22532 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022533 else
22534 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022535 my $Num = 0;
22536 foreach my $Name (split(/;/, $Line)) {
22537 $AddIntParams{$Interface}{$Num++}=$Name;
22538 }
22539 }
22540 }
22541 }
22542 }
22543 if($AppPath)
22544 {
22545 if(not -f $AppPath) {
22546 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22547 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022548
22549 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022550 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022551 $SymbolsList_App{$Interface} = 1;
22552 }
22553 }
22554 if($DumpAPI)
22555 { # --dump-abi
22556 # make an API dump
22557 create_ABI_Dump();
22558 exit($COMPILE_ERRORS);
22559 }
22560 # default: compare APIs
22561 # -d1 <path>
22562 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022563 compareInit();
22564 if($JoinReport or $DoubleReport)
22565 {
22566 compareAPIs("Binary");
22567 compareAPIs("Source");
22568 }
22569 elsif($BinaryOnly) {
22570 compareAPIs("Binary");
22571 }
22572 elsif($SourceOnly) {
22573 compareAPIs("Source");
22574 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022575 exitReport();
22576}
22577
22578scenario();