blob: 708cdd81daacc6d83e721da6ddf630a5712622e0 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03003# ABI Compliance Checker (ABICC) 1.99.14
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004# A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005#
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006# Copyright (C) 2009-2011 Institute for System Programming, RAS
7# Copyright (C) 2011-2012 Nokia Corporation and/or its subsidiary(-ies)
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +03008# Copyright (C) 2011-2012 ROSA Laboratory
9# Copyright (C) 2012-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 Ponomarenko99640d32015-11-01 21:20:50 +030041# ABI Dumper >= 0.99.12
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 Ponomarenko99640d32015-11-01 21:20:50 +030067my $TOOL_VERSION = "1.99.14";
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 Ponomarenko1fbbce62015-10-13 00:08:59 +030096$CheckInfo, $Quick, $AffectLimit, $AllAffected, $CppIncompat,
97$SkipInternalSymbols, $SkipInternalTypes, $TargetArch, $GccOptions,
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030098$TypesListPath, $SkipTypesListPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040099
100my $CmdName = get_filename($0);
101my %OS_LibExt = (
102 "dynamic" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400103 "linux"=>"so",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400104 "macos"=>"dylib",
105 "windows"=>"dll",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400106 "symbian"=>"dso",
107 "default"=>"so"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400108 },
109 "static" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400110 "linux"=>"a",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400111 "windows"=>"lib",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400112 "symbian"=>"lib",
113 "default"=>"a"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400114 }
115);
116
117my %OS_Archive = (
118 "windows"=>"zip",
119 "default"=>"tar.gz"
120);
121
122my %ERROR_CODE = (
123 # Compatible verdict
124 "Compatible"=>0,
125 "Success"=>0,
126 # Incompatible verdict
127 "Incompatible"=>1,
128 # Undifferentiated error code
129 "Error"=>2,
130 # System command is not found
131 "Not_Found"=>3,
132 # Cannot access input files
133 "Access_Error"=>4,
134 # Cannot compile header files
135 "Cannot_Compile"=>5,
136 # Header compiled with errors
137 "Compile_Error"=>6,
138 # Invalid input ABI dump
139 "Invalid_Dump"=>7,
140 # Incompatible version of ABI dump
141 "Dump_Version"=>8,
142 # Cannot find a module
143 "Module_Error"=>9,
144 # Empty intersection between
145 # headers and shared objects
146 "Empty_Intersection"=>10,
147 # Empty set of symbols in headers
148 "Empty_Set"=>11
149);
150
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300151my $HomePage = "http://lvc.github.io/abi-compliance-checker/";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400152
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400153my $ShortUsage = "ABI Compliance Checker (ABICC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400154A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300155Copyright (C) 2015 Andrey Ponomarenko's ABI Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400156License: GNU LGPL or GNU GPL
157
158Usage: $CmdName [options]
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400159Example: $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400160
161OLD.xml and NEW.xml are XML-descriptors:
162
163 <version>
164 1.0
165 </version>
166
167 <headers>
168 /path/to/headers/
169 </headers>
170
171 <libs>
172 /path/to/libraries/
173 </libs>
174
175More info: $CmdName --help\n";
176
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400177if($#ARGV==-1)
178{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400179 printMsg("INFO", $ShortUsage);
180 exit(0);
181}
182
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400183GetOptions("h|help!" => \$Help,
184 "i|info!" => \$InfoMsg,
185 "v|version!" => \$ShowVersion,
186 "dumpversion!" => \$DumpVersion,
187# general options
188 "l|lib|library=s" => \$TargetLibraryName,
189 "d1|old|o=s" => \$Descriptor{1}{"Path"},
190 "d2|new|n=s" => \$Descriptor{2}{"Path"},
191 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400192# extra options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400193 "app|application=s" => \$AppPath,
194 "static-libs!" => \$UseStaticLibs,
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +0400195 "gcc-path|cross-gcc=s" => \$CrossGcc,
196 "gcc-prefix|cross-prefix=s" => \$CrossPrefix,
197 "gcc-options=s" => \$GccOptions,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400198 "sysroot=s" => \$SystemRoot_Opt,
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +0300199 "v1|vnum1|version1|vnum=s" => \$TargetVersion{1},
200 "v2|vnum2|version2=s" => \$TargetVersion{2},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400201 "s|strict!" => \$StrictCompat,
202 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300203 "types-list=s" => \$TypesListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400204 "skip-symbols=s" => \$SkipSymbolsListPath,
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300205 "skip-types=s" => \$SkipTypesListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400206 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400207 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400208 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400209 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400210 "show-retval!" => \$ShowRetVal,
211 "use-dumps!" => \$UseDumps,
212 "nostdinc!" => \$NoStdInc,
213 "dump-system=s" => \$DumpSystem,
214 "sysinfo=s" => \$TargetSysInfo,
215 "cmp-systems!" => \$CmpSystems,
216 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400217 "ext|extended!" => \$ExtendedCheck,
218 "q|quiet!" => \$Quiet,
219 "stdout!" => \$StdOut,
220 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400221 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400222 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400223 "lang=s" => \$UserLang,
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400224 "arch=s" => \$TargetArch,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400225 "binary|bin|abi!" => \$BinaryOnly,
226 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400227 "limit-affected|affected-limit=s" => \$AffectLimit,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400228# other options
229 "test!" => \$TestTool,
230 "test-dump!" => \$TestDump,
231 "debug!" => \$Debug,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400232 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400233 "cpp-incompatible!" => \$CppIncompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400234 "p|params=s" => \$ParamNamesPath,
235 "relpath1|relpath=s" => \$RelativeDirectory{1},
236 "relpath2=s" => \$RelativeDirectory{2},
237 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400238 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400239 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400240 "bin-report-path=s" => \$BinaryReportPath,
241 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400242 "log-path=s" => \$LoggingPath,
243 "log1-path=s" => \$OutputLogPath{1},
244 "log2-path=s" => \$OutputLogPath{2},
245 "logging-mode=s" => \$LogMode,
246 "list-affected!" => \$ListAffected,
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300247 "title|l-full|lib-full=s" => \$TargetTitle,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400248 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400249 "extra-info=s" => \$ExtraInfo,
250 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400251 "force!" => \$Force,
252 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400253 "tolerant!" => \$Tolerant,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400254 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400255 "quick!" => \$Quick,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400256 "all-affected!" => \$AllAffected,
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300257 "skip-internal-symbols|skip-internal=s" => \$SkipInternalSymbols,
258 "skip-internal-types=s" => \$SkipInternalTypes,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400259) or ERR_MESSAGE();
260
261sub ERR_MESSAGE()
262{
263 printMsg("INFO", "\n".$ShortUsage);
264 exit($ERROR_CODE{"Error"});
265}
266
267my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
268my $SLIB_TYPE = $LIB_TYPE;
269if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
270{ # show as "shared" library
271 $SLIB_TYPE = "shared";
272}
273my $LIB_EXT = getLIB_EXT($OSgroup);
274my $AR_EXT = getAR_EXT($OSgroup);
275my $BYTE_SIZE = 8;
276my $COMMON_LOG_PATH = "logs/run.log";
277
278my $HelpMessage="
279NAME:
280 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400281 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400282
283DESCRIPTION:
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +0400284 ABI Compliance Checker (ABICC) is a tool for checking backward binary and
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400285 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
286 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
287 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
288 and/or source-level compatibility: changes in calling stack, v-table changes,
289 removed symbols, renamed fields, etc. Binary incompatibility may result in
290 crashing or incorrect behavior of applications built with an old version of
291 a library if they run on a new one. Source incompatibility may result in
292 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400293
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400294 The tool is intended for developers of software libraries and maintainers
295 of operating systems who are interested in ensuring backward compatibility,
296 i.e. allow old applications to run or to be recompiled with newer library
297 versions.
298
299 Also the tool can be used by ISVs for checking applications portability to
300 new library versions. Found issues can be taken into account when adapting
301 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400302
303 This tool is free software: you can redistribute it and/or modify it
304 under the terms of the GNU LGPL or GNU GPL.
305
306USAGE:
307 $CmdName [options]
308
309EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400310 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400311
312 OLD.xml and NEW.xml are XML-descriptors:
313
314 <version>
315 1.0
316 </version>
317
318 <headers>
319 /path1/to/header(s)/
320 /path2/to/header(s)/
321 ...
322 </headers>
323
324 <libs>
325 /path1/to/library(ies)/
326 /path2/to/library(ies)/
327 ...
328 </libs>
329
330INFORMATION OPTIONS:
331 -h|-help
332 Print this help.
333
334 -i|-info
335 Print complete info.
336
337 -v|-version
338 Print version information.
339
340 -dumpversion
341 Print the tool version ($TOOL_VERSION) and don't do anything else.
342
343GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400344 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400345 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400346
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400347 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400348 Descriptor of 1st (old) library version.
349 It may be one of the following:
350
351 1. XML-descriptor (VERSION.xml file):
352
353 <version>
354 1.0
355 </version>
356
357 <headers>
358 /path1/to/header(s)/
359 /path2/to/header(s)/
360 ...
361 </headers>
362
363 <libs>
364 /path1/to/library(ies)/
365 /path2/to/library(ies)/
366 ...
367 </libs>
368
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300369 ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400370
371 2. ABI dump generated by -dump option
372 3. Directory with headers and/or $SLIB_TYPE libraries
373 4. Single header file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400374
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +0300375 If you are using an 2-4 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400376 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400377
378 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400379 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400380
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400381 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400382 Descriptor of 2nd (new) library version.
383
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400384 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400385 Create library ABI dump for the input XML descriptor. You can
386 transfer it anywhere and pass instead of the descriptor. Also
387 it can be used for debugging the tool.
388
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +0300389 Supported versions of ABI dump: 2.0<=V<=$ABI_DUMP_VERSION\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400390
391sub HELP_MESSAGE() {
392 printMsg("INFO", $HelpMessage."
393MORE INFO:
394 $CmdName --info\n");
395}
396
397sub INFO_MESSAGE()
398{
399 printMsg("INFO", "$HelpMessage
400EXTRA OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400401 -app|-application PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300402 This option allows to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400403 for portability to the new library version.
404
405 -static-libs
406 Check static libraries instead of the shared ones. The <libs> section
407 of the XML-descriptor should point to static libraries location.
408
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300409 -gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400410 Path to the cross GCC compiler to use instead of the usual (host) GCC.
411
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300412 -gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400413 GCC toolchain prefix.
Andrey Ponomarenko8bfdcd82015-09-08 17:58:01 +0300414
415 -gcc-options OPTS
416 Additional compiler options.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400417
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400418 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400419 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400420 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400421
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400422 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400423 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200424 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400425
426 In general case you should specify it in the XML-descriptor:
427 <version>
428 VERSION
429 </version>
430
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400431 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400432 Specify 2nd library version outside the descriptor.
433
Andrey Ponomarenkoc5221342014-09-24 16:43:03 +0400434 -vnum NUM
435 Specify the library version in the generated ABI dump. The <version> section
436 of the input XML descriptor will be overwritten in this case.
437
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400438 -s|-strict
439 Treat all compatibility warnings as problems. Add a number of \"Low\"
440 severity problems to the return value of the tool.
441
442 -headers-only
443 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
444 provide a low quality compatibility report with false positives and
445 without detecting of added/removed symbols.
446
447 Alternatively you can write \"none\" word to the <libs> section
448 in the XML-descriptor:
449 <libs>
450 none
451 </libs>
452
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400453 -show-retval
454 Show the symbol's return type in the report.
455
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400456 -symbols-list PATH
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300457 This option allows to specify a file with a list of symbols (mangled
458 names in C++) that should be checked. Other symbols will not be checked.
459
460 -types-list PATH
461 This option allows to specify a file with a list of types that should
462 be checked. Other types will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400463
464 -skip-symbols PATH
Andrey Ponomarenko99640d32015-11-01 21:20:50 +0300465 The list of symbols that should not be checked.
466
467 -skip-types PATH
468 The list of types that should not be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400469
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400470 -headers-list PATH
471 The file with a list of headers, that should be checked/dumped.
472
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400473 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400474 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400475
476 -header NAME
477 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400478
479 -use-dumps
480 Make dumps for two versions of a library and compare dumps. This should
481 increase the performance of the tool and decrease the system memory usage.
482
483 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400484 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400485
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400486 -dump-system NAME -sysroot DIR
487 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400488 create XML descriptors and make ABI dumps for each library. The result
489 set of ABI dumps can be compared (--cmp-systems) with the other one
490 created for other version of operating system in order to check them for
491 compatibility. Do not forget to specify -cross-gcc option if your target
492 system requires some specific version of GCC compiler (different from
493 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400494 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400495
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400496 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400497 The same as the previous option but takes an XML descriptor of the target
498 system as input, where you should describe it:
499
500 /* Primary sections */
501
502 <name>
503 /* Name of the system */
504 </name>
505
506 <headers>
507 /* The list of paths to header files and/or
508 directories with header files, one per line */
509 </headers>
510
511 <libs>
512 /* The list of paths to shared libraries and/or
513 directories with shared libraries, one per line */
514 </libs>
515
516 /* Optional sections */
517
518 <search_headers>
519 /* List of directories to be searched
520 for header files to automatically
521 generate include paths, one per line */
522 </search_headers>
523
524 <search_libs>
525 /* List of directories to be searched
526 for shared libraries to resolve
527 dependencies, one per line */
528 </search_libs>
529
530 <tools>
531 /* List of directories with tools used
532 for analysis (GCC toolchain), one per line */
533 </tools>
534
535 <cross_prefix>
536 /* GCC toolchain prefix.
537 Examples:
538 arm-linux-gnueabi
539 arm-none-symbianelf */
540 </cross_prefix>
541
542 <gcc_options>
543 /* Additional GCC options, one per line */
544 </gcc_options>
545
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400546 -sysinfo DIR
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300547 This option should be used with -dump-system option to dump
548 ABI of operating systems and configure the dumping process.
549 You can find a sample in the package:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400550 modules/Targets/{unix, symbian, windows}
551
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400552 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400553 Compare two system ABI dumps. Create compatibility reports for each
554 library and the common HTML report including the summary of test
555 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400556 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400557
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400558 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400559 The file with a list of libraries, that should be dumped by
560 the -dump-system option or should be checked by the -cmp-systems option.
561
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400562 -ext|-extended
563 If your library A is supposed to be used by other library B and you
564 want to control the ABI of B, then you should enable this option. The
565 tool will check for changes in all data types, even if they are not
566 used by any function in the library A. Such data types are not part
567 of the A library ABI, but may be a part of the ABI of the B library.
568
569 The short scheme is:
570 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
571
572 -q|-quiet
573 Print all messages to the file instead of stdout and stderr.
574 Default path (can be changed by -log-path option):
575 $COMMON_LOG_PATH
576
577 -stdout
578 Print analysis results (compatibility reports and ABI dumps) to stdout
579 instead of creating a file. This would allow piping data to other programs.
580
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400581 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400582 Change format of compatibility report.
583 Formats:
584 htm - HTML format (default)
585 xml - XML format
586
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400587 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400588 Change format of ABI dump.
589 Formats:
590 perl - Data::Dumper format (default)
591 xml - XML format
592
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400593 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400594 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400595
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400596 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400597 Set library language (C or C++). You can use this option if the tool
598 cannot auto-detect a language. This option may be useful for checking
599 C-library headers (--lang=C) in --headers-only or --extended modes.
Andrey Ponomarenko54040a12014-03-04 19:01:13 +0400600
601 -arch ARCH
602 Set library architecture (x86, x86_64, ia64, arm, ppc32, ppc64, s390,
603 ect.). The option is useful if the tool cannot detect correct architecture
604 of the input objects.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400605
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400606 -binary|-bin|-abi
607 Show \"Binary\" compatibility problems only.
608 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400609 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400610
611 -source|-src|-api
612 Show \"Source\" compatibility problems only.
613 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400614 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400615
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400616 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400617 The maximum number of affected symbols listed under the description
618 of the changed type in the report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400619
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400620OTHER OPTIONS:
621 -test
622 Run internal tests. Create two binary incompatible versions of a sample
623 library and run the tool to check them for compatibility. This option
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300624 allows to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400625
626 -test-dump
627 Test ability to create, read and compare ABI dumps.
628
629 -debug
630 Debugging mode. Print debug info on the screen. Save intermediate
631 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400632 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400633
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400634 Also consider using --dump option for debugging the tool.
635
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400636 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400637 If your header files are written in C language and can be compiled
638 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
639 the tool about this and speedup the analysis.
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400640
641 -cpp-incompatible
642 Set this option if input C header files use C++ keywords.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400643
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400644 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400645 Path to file with the function parameter names. It can be used
646 for improving report view if the library header files have no
647 parameter names. File format:
648
649 func1;param1;param2;param3 ...
650 func2;param1;param2;param3 ...
651 ...
652
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400653 -relpath PATH
654 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400655 for dumping the library ABI (see -dump option).
656
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400657 -relpath1 PATH
658 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400659
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400660 -relpath2 PATH
661 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400662
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400663 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400664 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400665 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400666 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400667
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400668 -sort
669 Enable sorting of data in ABI dumps.
670
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400671 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400672 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400673 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400674 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400675
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400676 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400677 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400678 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400679 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400680
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400681 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400682 Path to \"Source\" compatibility report.
683 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400684 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400685
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400686 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400687 Log path for all messages.
688 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400689 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400690
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400691 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400692 Log path for 1st version of a library.
693 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400694 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400695
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400696 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400697 Log path for 2nd version of a library.
698 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400699 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400700
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400701 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400702 Change logging mode.
703 Modes:
704 w - overwrite old logs (default)
705 a - append old logs
706 n - do not write any logs
707
708 -list-affected
709 Generate file with the list of incompatible
710 symbols beside the HTML compatibility report.
711 Use 'c++filt \@file' command from GNU binutils
712 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400713 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400714 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400715 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400716
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400717 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400718 The component name in the title and summary of the HTML report.
719 Default:
720 library
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +0300721
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +0300722 -title NAME
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400723 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400724 will be displayed a name specified by -l option.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400725
726 -extra-info DIR
727 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400728
729 -extra-dump
730 Create extended ABI dump containing all symbols
731 from the translation unit.
732
733 -force
734 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400735
736 -tolerance LEVEL
737 Apply a set of heuristics to successfully compile input
738 header files. You can enable several tolerance levels by
739 joining them into one string (e.g. 13, 124, etc.).
740 Levels:
741 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
742 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
743 3 - skip headers that iclude non-Linux headers
744 4 - skip headers included by others
745
746 -tolerant
747 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400748
749 -check
750 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400751
752 -quick
753 Quick analysis. Disable check of some template instances.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400754
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +0300755 -skip-internal-symbols PATTERN
756 Do not check symbols matched by the pattern.
757
758 -skip-internal-types PATTERN
759 Do not check types matched by the pattern.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400760
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400761REPORT:
762 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400763 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400764
765 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400766 logs/LIB_NAME/V1/log.txt
767 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400768
769EXIT CODES:
770 0 - Compatible. The tool has run without any errors.
771 non-zero - Incompatible or the tool has run with errors.
772
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400773MORE INFORMATION:
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +0300774 ".$HomePage."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400775}
776
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400777my %Operator_Indication = (
778 "not" => "~",
779 "assign" => "=",
780 "andassign" => "&=",
781 "orassign" => "|=",
782 "xorassign" => "^=",
783 "or" => "|",
784 "xor" => "^",
785 "addr" => "&",
786 "and" => "&",
787 "lnot" => "!",
788 "eq" => "==",
789 "ne" => "!=",
790 "lt" => "<",
791 "lshift" => "<<",
792 "lshiftassign" => "<<=",
793 "rshiftassign" => ">>=",
794 "call" => "()",
795 "mod" => "%",
796 "modassign" => "%=",
797 "subs" => "[]",
798 "land" => "&&",
799 "lor" => "||",
800 "rshift" => ">>",
801 "ref" => "->",
802 "le" => "<=",
803 "deref" => "*",
804 "mult" => "*",
805 "preinc" => "++",
806 "delete" => " delete",
807 "vecnew" => " new[]",
808 "vecdelete" => " delete[]",
809 "predec" => "--",
810 "postinc" => "++",
811 "postdec" => "--",
812 "plusassign" => "+=",
813 "plus" => "+",
814 "minus" => "-",
815 "minusassign" => "-=",
816 "gt" => ">",
817 "ge" => ">=",
818 "new" => " new",
819 "multassign" => "*=",
820 "divassign" => "/=",
821 "div" => "/",
822 "neg" => "-",
823 "pos" => "+",
824 "memref" => "->*",
825 "compound" => "," );
826
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400827my %UnknownOperator;
828
829my %NodeType= (
830 "array_type" => "Array",
831 "binfo" => "Other",
832 "boolean_type" => "Intrinsic",
833 "complex_type" => "Intrinsic",
834 "const_decl" => "Other",
835 "enumeral_type" => "Enum",
836 "field_decl" => "Other",
837 "function_decl" => "Other",
838 "function_type" => "FunctionType",
839 "identifier_node" => "Other",
840 "integer_cst" => "Other",
841 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400842 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400843 "method_type" => "MethodType",
844 "namespace_decl" => "Other",
845 "parm_decl" => "Other",
846 "pointer_type" => "Pointer",
847 "real_cst" => "Other",
848 "real_type" => "Intrinsic",
849 "record_type" => "Struct",
850 "reference_type" => "Ref",
851 "string_cst" => "Other",
852 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400853 "template_type_parm" => "TemplateParam",
854 "typename_type" => "TypeName",
855 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400856 "tree_list" => "Other",
857 "tree_vec" => "Other",
858 "type_decl" => "Other",
859 "union_type" => "Union",
860 "var_decl" => "Other",
861 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400862 "nop_expr" => "Other", #
863 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400864 "offset_type" => "Other" );
865
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400866my %CppKeywords_C = map {$_=>1} (
867 # C++ 2003 keywords
868 "public",
869 "protected",
870 "private",
871 "default",
872 "template",
873 "new",
874 #"asm",
875 "dynamic_cast",
876 "auto",
877 "try",
878 "namespace",
879 "typename",
880 "using",
881 "reinterpret_cast",
882 "friend",
883 "class",
884 "virtual",
885 "const_cast",
886 "mutable",
887 "static_cast",
888 "export",
889 # C++0x keywords
890 "noexcept",
891 "nullptr",
892 "constexpr",
893 "static_assert",
894 "explicit",
895 # cannot be used as a macro name
896 # as it is an operator in C++
897 "and",
898 #"and_eq",
899 "not",
900 #"not_eq",
901 "or"
902 #"or_eq",
903 #"bitand",
904 #"bitor",
905 #"xor",
906 #"xor_eq",
907 #"compl"
908);
909
910my %CppKeywords_F = map {$_=>1} (
911 "delete",
912 "catch",
913 "alignof",
914 "thread_local",
915 "decltype",
916 "typeid"
917);
918
919my %CppKeywords_O = map {$_=>1} (
920 "bool",
921 "register",
922 "inline",
923 "operator"
924);
925
926my %CppKeywords_A = map {$_=>1} (
927 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400928 "throw",
929 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400930);
931
932foreach (keys(%CppKeywords_C),
933keys(%CppKeywords_F),
934keys(%CppKeywords_O)) {
935 $CppKeywords_A{$_}=1;
936}
937
938# Header file extensions as described by gcc
939my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
940
941my %IntrinsicMangling = (
942 "void" => "v",
943 "bool" => "b",
944 "wchar_t" => "w",
945 "char" => "c",
946 "signed char" => "a",
947 "unsigned char" => "h",
948 "short" => "s",
949 "unsigned short" => "t",
950 "int" => "i",
951 "unsigned int" => "j",
952 "long" => "l",
953 "unsigned long" => "m",
954 "long long" => "x",
955 "__int64" => "x",
956 "unsigned long long" => "y",
957 "__int128" => "n",
958 "unsigned __int128" => "o",
959 "float" => "f",
960 "double" => "d",
961 "long double" => "e",
962 "__float80" => "e",
963 "__float128" => "g",
964 "..." => "z"
965);
966
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400967my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
968
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400969my %StdcxxMangling = (
970 "3std"=>"St",
971 "3std9allocator"=>"Sa",
972 "3std12basic_string"=>"Sb",
973 "3std12basic_stringIcE"=>"Ss",
974 "3std13basic_istreamIcE"=>"Si",
975 "3std13basic_ostreamIcE"=>"So",
976 "3std14basic_iostreamIcE"=>"Sd"
977);
978
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +0400979my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400980my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
981
982my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400983my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400984
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400985my %ConstantSuffix = (
986 "unsigned int"=>"u",
987 "long"=>"l",
988 "unsigned long"=>"ul",
989 "long long"=>"ll",
990 "unsigned long long"=>"ull"
991);
992
993my %ConstantSuffixR =
994reverse(%ConstantSuffix);
995
996my %OperatorMangling = (
997 "~" => "co",
998 "=" => "aS",
999 "|" => "or",
1000 "^" => "eo",
1001 "&" => "an",#ad (addr)
1002 "==" => "eq",
1003 "!" => "nt",
1004 "!=" => "ne",
1005 "<" => "lt",
1006 "<=" => "le",
1007 "<<" => "ls",
1008 "<<=" => "lS",
1009 ">" => "gt",
1010 ">=" => "ge",
1011 ">>" => "rs",
1012 ">>=" => "rS",
1013 "()" => "cl",
1014 "%" => "rm",
1015 "[]" => "ix",
1016 "&&" => "aa",
1017 "||" => "oo",
1018 "*" => "ml",#de (deref)
1019 "++" => "pp",#
1020 "--" => "mm",#
1021 "new" => "nw",
1022 "delete" => "dl",
1023 "new[]" => "na",
1024 "delete[]" => "da",
1025 "+=" => "pL",
1026 "+" => "pl",#ps (pos)
1027 "-" => "mi",#ng (neg)
1028 "-=" => "mI",
1029 "*=" => "mL",
1030 "/=" => "dV",
1031 "&=" => "aN",
1032 "|=" => "oR",
1033 "%=" => "rM",
1034 "^=" => "eO",
1035 "/" => "dv",
1036 "->*" => "pm",
1037 "->" => "pt",#rf (ref)
1038 "," => "cm",
1039 "?" => "qu",
1040 "." => "dt",
1041 "sizeof"=> "sz"#st
1042);
1043
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001044my %Intrinsic_Keywords = map {$_=>1} (
1045 "true",
1046 "false",
1047 "_Bool",
1048 "_Complex",
1049 "const",
1050 "int",
1051 "long",
1052 "void",
1053 "short",
1054 "float",
1055 "volatile",
1056 "restrict",
1057 "unsigned",
1058 "signed",
1059 "char",
1060 "double",
1061 "class",
1062 "struct",
1063 "union",
1064 "enum"
1065);
1066
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001067my %GlibcHeader = map {$_=>1} (
1068 "aliases.h",
1069 "argp.h",
1070 "argz.h",
1071 "assert.h",
1072 "cpio.h",
1073 "ctype.h",
1074 "dirent.h",
1075 "envz.h",
1076 "errno.h",
1077 "error.h",
1078 "execinfo.h",
1079 "fcntl.h",
1080 "fstab.h",
1081 "ftw.h",
1082 "glob.h",
1083 "grp.h",
1084 "iconv.h",
1085 "ifaddrs.h",
1086 "inttypes.h",
1087 "langinfo.h",
1088 "limits.h",
1089 "link.h",
1090 "locale.h",
1091 "malloc.h",
1092 "math.h",
1093 "mntent.h",
1094 "monetary.h",
1095 "nl_types.h",
1096 "obstack.h",
1097 "printf.h",
1098 "pwd.h",
1099 "regex.h",
1100 "sched.h",
1101 "search.h",
1102 "setjmp.h",
1103 "shadow.h",
1104 "signal.h",
1105 "spawn.h",
1106 "stdarg.h",
1107 "stdint.h",
1108 "stdio.h",
1109 "stdlib.h",
1110 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001111 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001112 "tar.h",
1113 "termios.h",
1114 "time.h",
1115 "ulimit.h",
1116 "unistd.h",
1117 "utime.h",
1118 "wchar.h",
1119 "wctype.h",
1120 "wordexp.h" );
1121
1122my %GlibcDir = map {$_=>1} (
1123 "arpa",
1124 "bits",
1125 "gnu",
1126 "netinet",
1127 "net",
1128 "nfs",
1129 "rpc",
1130 "sys",
1131 "linux" );
1132
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001133my %WinHeaders = map {$_=>1} (
1134 "dos.h",
1135 "process.h",
1136 "winsock.h",
1137 "config-win.h",
1138 "mem.h",
1139 "windows.h",
1140 "winsock2.h",
1141 "crtdbg.h",
1142 "ws2tcpip.h"
1143);
1144
1145my %ObsoleteHeaders = map {$_=>1} (
1146 "iostream.h",
1147 "fstream.h"
1148);
1149
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001150my %AlienHeaders = map {$_=>1} (
1151 # Solaris
1152 "thread.h",
1153 "sys/atomic.h",
1154 # HPUX
1155 "sys/stream.h",
1156 # Symbian
1157 "AknDoc.h",
1158 # Atari ST
1159 "ext.h",
1160 "tos.h",
1161 # MS-DOS
1162 "alloc.h",
1163 # Sparc
1164 "sys/atomic.h"
1165);
1166
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001167my %ConfHeaders = map {$_=>1} (
1168 "atomic",
1169 "conf.h",
1170 "config.h",
1171 "configure.h",
1172 "build.h",
1173 "setup.h"
1174);
1175
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001176my %LocalIncludes = map {$_=>1} (
1177 "/usr/local/include",
1178 "/usr/local" );
1179
1180my %OS_AddPath=(
1181# These paths are needed if the tool cannot detect them automatically
1182 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001183 "include"=>[
1184 "/Library",
1185 "/Developer/usr/include"
1186 ],
1187 "lib"=>[
1188 "/Library",
1189 "/Developer/usr/lib"
1190 ],
1191 "bin"=>[
1192 "/Developer/usr/bin"
1193 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001194 },
1195 "beos"=>{
1196 # Haiku has GCC 2.95.3 by default
1197 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001198 "include"=>[
1199 "/boot/common",
1200 "/boot/develop"
1201 ],
1202 "lib"=>[
1203 "/boot/common/lib",
1204 "/boot/system/lib",
1205 "/boot/apps"
1206 ],
1207 "bin"=>[
1208 "/boot/common/bin",
1209 "/boot/system/bin",
1210 "/boot/develop/abi"
1211 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001212 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001213);
1214
1215my %Slash_Type=(
1216 "default"=>"/",
1217 "windows"=>"\\"
1218);
1219
1220my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1221
1222# Global Variables
1223my %COMMON_LANGUAGE=(
1224 1 => "C",
1225 2 => "C" );
1226
1227my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001228my $MAX_CPPFILT_FILE_SIZE = 50000;
1229my $CPPFILT_SUPPORT_FILE;
1230
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001231my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1232
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001233my $STDCXX_TESTING = 0;
1234my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001235my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001236
1237my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001238my $CheckUndefined = 0;
1239
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +03001240my $TargetComponent = undef;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001241if($TargetComponent_Opt) {
1242 $TargetComponent = lc($TargetComponent_Opt);
1243}
1244else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001245{ # default: library
1246 # other components: header, system, ...
1247 $TargetComponent = "library";
1248}
1249
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001250my $TOP_REF = "<a class='top_ref' href='#Top'>to the top</a>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001251
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001252my $SystemRoot;
1253
1254my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001255my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001256my %LOG_PATH;
1257my %DEBUG_PATH;
1258my %Cache;
1259my %LibInfo;
1260my $COMPILE_ERRORS = 0;
1261my %CompilerOptions;
1262my %CheckedDyLib;
1263my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1264
1265# Constants (#defines)
1266my %Constants;
1267my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001268my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001269
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001270# Extra Info
1271my %SymbolHeader;
1272my %KnownLibs;
1273
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001274# Templates
1275my %TemplateInstance;
1276my %BasicTemplate;
1277my %TemplateArg;
1278my %TemplateDecl;
1279my %TemplateMap;
1280
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001281# Types
1282my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001283my %SkipTypes = (
1284 "1"=>{},
1285 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001286my %CheckedTypes;
1287my %TName_Tid;
1288my %EnumMembName_Id;
1289my %NestedNameSpaces = (
1290 "1"=>{},
1291 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001292my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001293my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001294my %ClassVTable;
1295my %ClassVTable_Content;
1296my %VTableClass;
1297my %AllocableClass;
1298my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001299my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001300my %Class_SubClasses;
1301my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001302my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001303my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001304
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001305my %CheckedTypeInfo;
1306
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001307# Typedefs
1308my %Typedef_BaseName;
1309my %Typedef_Tr;
1310my %Typedef_Eq;
1311my %StdCxxTypedef;
1312my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001313my %MissedBase;
1314my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001315my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001316
1317# Symbols
1318my %SymbolInfo;
1319my %tr_name;
1320my %mangled_name_gcc;
1321my %mangled_name;
1322my %SkipSymbols = (
1323 "1"=>{},
1324 "2"=>{} );
1325my %SkipNameSpaces = (
1326 "1"=>{},
1327 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001328my %AddNameSpaces = (
1329 "1"=>{},
1330 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001331my %SymbolsList;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +03001332my %TypesList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001333my %SymbolsList_App;
1334my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001335my %Symbol_Library = (
1336 "1"=>{},
1337 "2"=>{} );
1338my %Library_Symbol = (
1339 "1"=>{},
1340 "2"=>{} );
1341my %DepSymbol_Library = (
1342 "1"=>{},
1343 "2"=>{} );
1344my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001345 "1"=>{},
1346 "2"=>{} );
1347my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001348my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001349my %AddIntParams;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001350my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001351my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001352my %Library_Needed= (
1353 "1"=>{},
1354 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001355
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001356# Extra Info
1357my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001358my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001359
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001360# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001361my %Include_Preamble = (
1362 "1"=>[],
1363 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001364my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001365my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001366my %HeaderName_Paths;
1367my %Header_Dependency;
1368my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001369my %Include_Paths = (
1370 "1"=>[],
1371 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001372my %INC_PATH_AUTODETECT = (
1373 "1"=>1,
1374 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001375my %Add_Include_Paths = (
1376 "1"=>[],
1377 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001378my %Skip_Include_Paths;
1379my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001380my %Header_ErrorRedirect;
1381my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001382my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001383my %Header_ShouldNotBeUsed;
1384my %RecursiveIncludes;
1385my %Header_Include_Prefix;
1386my %SkipHeaders;
1387my %SkipHeadersList=(
1388 "1"=>{},
1389 "2"=>{} );
1390my %SkipLibs;
1391my %Include_Order;
1392my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001393my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001394my %TUnit_Funcs;
1395my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001396
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001397my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001398 "1"=>0,
1399 "2"=>0 );
1400my %AutoPreambleMode = (
1401 "1"=>0,
1402 "2"=>0 );
1403my %MinGWMode = (
1404 "1"=>0,
1405 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001406my %Cpp0xMode = (
1407 "1"=>0,
1408 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001409
1410# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001411my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001412my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001413my %RegisteredSONAMEs;
1414my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001415
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04001416my %CheckedArch;
1417
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001418# System Objects
1419my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001420my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001421my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001422
1423# System Headers
1424my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001425my @DefaultCppPaths;
1426my @DefaultGccPaths;
1427my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001428my %DefaultCppHeader;
1429my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001430my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001431
1432# Merging
1433my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001434my $Version;
1435my %AddedInt;
1436my %RemovedInt;
1437my %AddedInt_Virt;
1438my %RemovedInt_Virt;
1439my %VirtualReplacement;
1440my %ChangedTypedef;
1441my %CompatRules;
1442my %IncompleteRules;
1443my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001444my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001445my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001446my %ReturnedClass;
1447my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001448my %SourceAlternative;
1449my %SourceAlternative_B;
1450my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001451my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001452
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001453# Calling Conventions
1454my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001455 1=>{ "R"=>0, "P"=>0 },
1456 2=>{ "R"=>0, "P"=>0 }
1457);
1458
1459# ABI Dump
1460my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001461
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001462# Filters
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001463my %TargetLibs;
1464my %TargetHeaders;
1465
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03001466# Format of objects
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001467my $OStarget = $OSgroup;
1468my %TargetTools;
1469
1470# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001471my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001472
1473# Recursion locks
1474my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001475my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001476my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001477my @RecurInclude;
1478my @RecurConstant;
1479
1480# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001481my %SystemPaths = (
1482 "include"=>[],
1483 "lib"=>[],
1484 "bin"=>[]
1485);
1486my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001487my $GCC_PATH;
1488
1489# Symbols versioning
1490my %SymVer = (
1491 "1"=>{},
1492 "2"=>{} );
1493
1494# Problem descriptions
1495my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001496my %CompatProblems_Constants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001497my %TotalAffected;
1498
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001499# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001500my $ContentID = 1;
1501my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1502my $ContentSpanStart_Affected = "<span class=\"section_affected\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1503my $ContentSpanStart_Info = "<span class=\"section_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1504my $ContentSpanEnd = "</span>\n";
1505my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1506my $ContentDivEnd = "</div>\n";
1507my $Content_Counter = 0;
1508
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001509# Modes
1510my $JoinReport = 1;
1511my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001512
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001513my %Severity_Val=(
1514 "High"=>3,
1515 "Medium"=>2,
1516 "Low"=>1,
1517 "Safe"=>-1
1518);
1519
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001520sub get_Modules()
1521{
1522 my $TOOL_DIR = get_dirname($0);
1523 if(not $TOOL_DIR)
1524 { # patch for MS Windows
1525 $TOOL_DIR = ".";
1526 }
1527 my @SEARCH_DIRS = (
1528 # tool's directory
1529 abs_path($TOOL_DIR),
1530 # relative path to modules
1531 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001532 # install path
1533 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001534 );
1535 foreach my $DIR (@SEARCH_DIRS)
1536 {
1537 if(not is_abs($DIR))
1538 { # relative path
1539 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1540 }
1541 if(-d $DIR."/modules") {
1542 return $DIR."/modules";
1543 }
1544 }
1545 exitStatus("Module_Error", "can't find modules");
1546}
1547
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001548my %LoadedModules = ();
1549
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001550sub loadModule($)
1551{
1552 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001553 if(defined $LoadedModules{$Name}) {
1554 return;
1555 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001556 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1557 if(not -f $Path) {
1558 exitStatus("Module_Error", "can't access \'$Path\'");
1559 }
1560 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001561 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001562}
1563
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001564sub readModule($$)
1565{
1566 my ($Module, $Name) = @_;
1567 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1568 if(not -f $Path) {
1569 exitStatus("Module_Error", "can't access \'$Path\'");
1570 }
1571 return readFile($Path);
1572}
1573
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001574sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001575{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001576 my $Number = $_[0];
1577 if(not $Number) {
1578 $Number = 1;
1579 }
1580 else {
1581 $Number = int($Number)+1;
1582 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001583 if($Number>3) {
1584 return $Number."th";
1585 }
1586 elsif($Number==1) {
1587 return "1st";
1588 }
1589 elsif($Number==2) {
1590 return "2nd";
1591 }
1592 elsif($Number==3) {
1593 return "3rd";
1594 }
1595 else {
1596 return $Number;
1597 }
1598}
1599
1600sub search_Tools($)
1601{
1602 my $Name = $_[0];
1603 return "" if(not $Name);
1604 if(my @Paths = keys(%TargetTools))
1605 {
1606 foreach my $Path (@Paths)
1607 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001608 if(-f join_P($Path, $Name)) {
1609 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001610 }
1611 if($CrossPrefix)
1612 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001613 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001614 if(-f $Candidate) {
1615 return $Candidate;
1616 }
1617 }
1618 }
1619 }
1620 else {
1621 return "";
1622 }
1623}
1624
1625sub synch_Cmd($)
1626{
1627 my $Name = $_[0];
1628 if(not $GCC_PATH)
1629 { # GCC was not found yet
1630 return "";
1631 }
1632 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001633 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001634 return $Candidate;
1635 }
1636 return "";
1637}
1638
1639sub get_CmdPath($)
1640{
1641 my $Name = $_[0];
1642 return "" if(not $Name);
1643 if(defined $Cache{"get_CmdPath"}{$Name}) {
1644 return $Cache{"get_CmdPath"}{$Name};
1645 }
1646 my %BinUtils = map {$_=>1} (
1647 "c++filt",
1648 "objdump",
1649 "readelf"
1650 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001651 if($BinUtils{$Name} and $GCC_PATH)
1652 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001653 if(my $Dir = get_dirname($GCC_PATH)) {
1654 $TargetTools{$Dir}=1;
1655 }
1656 }
1657 my $Path = search_Tools($Name);
1658 if(not $Path and $OSgroup eq "windows") {
1659 $Path = search_Tools($Name.".exe");
1660 }
1661 if(not $Path and $BinUtils{$Name})
1662 {
1663 if($CrossPrefix)
1664 { # user-defined prefix
1665 $Path = search_Cmd($CrossPrefix."-".$Name);
1666 }
1667 }
1668 if(not $Path and $BinUtils{$Name})
1669 {
1670 if(my $Candidate = synch_Cmd($Name))
1671 { # synch with GCC
1672 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001673 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001674 if(-f $Candidate) {
1675 $Path = $Candidate;
1676 }
1677 }
1678 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001679 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001680 $Path = $Candidate;
1681 }
1682 }
1683 }
1684 if(not $Path) {
1685 $Path = search_Cmd($Name);
1686 }
1687 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001688 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001689 $Path=search_Cmd($Name.".exe");
1690 }
1691 if($Path=~/\s/) {
1692 $Path = "\"".$Path."\"";
1693 }
1694 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1695}
1696
1697sub search_Cmd($)
1698{
1699 my $Name = $_[0];
1700 return "" if(not $Name);
1701 if(defined $Cache{"search_Cmd"}{$Name}) {
1702 return $Cache{"search_Cmd"}{$Name};
1703 }
1704 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1705 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1706 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001707 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001708 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001709 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001710 if(-f $CmdPath)
1711 {
1712 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001713 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001714 }
1715 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1716 }
1717 }
1718 return ($Cache{"search_Cmd"}{$Name} = "");
1719}
1720
1721sub get_CmdPath_Default($)
1722{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001723 return "" if(not $_[0]);
1724 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1725 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001726 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001727 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1728}
1729
1730sub get_CmdPath_Default_I($)
1731{ # search in PATH
1732 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001733 if($Name=~/find/)
1734 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001735 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001736 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001737 }
1738 }
1739 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001740 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001741 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001742 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001743 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001744 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001745 if($OSgroup eq "windows")
1746 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001747 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001748 return $Name;
1749 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001750 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001751 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001752 {
1753 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001754 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001755 }
1756 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001757 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001758}
1759
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001760sub classifyPath($)
1761{
1762 my $Path = $_[0];
1763 if($Path=~/[\*\[]/)
1764 { # wildcard
1765 $Path=~s/\*/.*/g;
1766 $Path=~s/\\/\\\\/g;
1767 return ($Path, "Pattern");
1768 }
1769 elsif($Path=~/[\/\\]/)
1770 { # directory or relative path
1771 return (path_format($Path, $OSgroup), "Path");
1772 }
1773 else {
1774 return ($Path, "Name");
1775 }
1776}
1777
1778sub readDescriptor($$)
1779{
1780 my ($LibVersion, $Content) = @_;
1781 return if(not $LibVersion);
1782 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1783 if(not $Content) {
1784 exitStatus("Error", "$DName is empty");
1785 }
1786 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001787 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001788 }
1789 $Content=~s/\/\*(.|\n)+?\*\///g;
1790 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001791
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001792 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1793 if($TargetVersion{$LibVersion}) {
1794 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1795 }
1796 if(not $Descriptor{$LibVersion}{"Version"}) {
1797 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1798 }
1799 if($Content=~/{RELPATH}/)
1800 {
1801 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1802 $Content =~ s/{RELPATH}/$RelDir/g;
1803 }
1804 else
1805 {
1806 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1807 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1808 }
1809 }
1810
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001811 my $DHeaders = parseTag(\$Content, "headers");
1812 if(not $DHeaders) {
1813 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1814 }
1815 elsif(lc($DHeaders) ne "none")
1816 { # append the descriptor headers list
1817 if($Descriptor{$LibVersion}{"Headers"})
1818 { # multiple descriptors
1819 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001820 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001821 else {
1822 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1823 }
1824 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1825 {
1826 if(not -e $Path) {
1827 exitStatus("Access_Error", "can't access \'$Path\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001828 }
1829 }
1830 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03001831
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001832 if(not $CheckHeadersOnly_Opt)
1833 {
1834 my $DObjects = parseTag(\$Content, "libs");
1835 if(not $DObjects) {
1836 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1837 }
1838 elsif(lc($DObjects) ne "none")
1839 { # append the descriptor libraries list
1840 if($Descriptor{$LibVersion}{"Libs"})
1841 { # multiple descriptors
1842 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1843 }
1844 else {
1845 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1846 }
1847 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1848 {
1849 if(not -e $Path) {
1850 exitStatus("Access_Error", "can't access \'$Path\'");
1851 }
1852 }
1853 }
1854 }
1855 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
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{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001863 }
1864 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
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{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001872 }
1873 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1874 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001875 if(not -d $Path) {
1876 exitStatus("Access_Error", "can't access directory \'$Path\'");
1877 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001878 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001879 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001880 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001881 $TargetTools{$Path}=1;
1882 }
1883 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
1884 $CrossPrefix = $Prefix;
1885 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001886 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001887 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
1888 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001889 if(not -d $Path) {
1890 exitStatus("Access_Error", "can't access directory \'$Path\'");
1891 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001892 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001893 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001894 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001895 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001896 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001897 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
1898 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001899 if(not -d $Path) {
1900 exitStatus("Access_Error", "can't access directory \'$Path\'");
1901 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001902 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001903 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001904 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001905 }
1906 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001907 { # skip some auto-generated include paths
1908 if(not is_abs($Path))
1909 {
1910 if(my $P = abs_path($Path)) {
1911 $Path = $P;
1912 }
1913 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001914 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001915 }
1916 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001917 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001918 my ($CPath, $Type) = classifyPath($Path);
1919 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001920 }
1921 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001922 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
1923 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001924 if($Option!~/\A\-(Wl|l|L)/)
1925 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001926 $CompilerOptions{$LibVersion} .= " ".$Option;
1927 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001928 }
1929 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
1930 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
1931 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001932 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001933 my ($CPath, $Type) = classifyPath($Path);
1934 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001935 }
1936 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
1937 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
1938 {
1939 my ($CPath, $Type) = classifyPath($Path);
1940 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
1941 }
1942 if(my $DDefines = parseTag(\$Content, "defines"))
1943 {
1944 if($Descriptor{$LibVersion}{"Defines"})
1945 { # multiple descriptors
1946 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
1947 }
1948 else {
1949 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
1950 }
1951 }
1952 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
1953 {
1954 if($Order=~/\A(.+):(.+)\Z/) {
1955 $Include_Order{$LibVersion}{$1} = $2;
1956 }
1957 }
1958 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
1959 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001960 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001961 $SkipTypes{$LibVersion}{$Type_Name} = 1;
1962 }
1963 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
1964 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001965 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001966 $SkipSymbols{$LibVersion}{$Symbol} = 1;
1967 }
1968 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
1969 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
1970 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001971 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
1972 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
1973 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001974 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
1975 $SkipConstants{$LibVersion}{$Constant} = 1;
1976 }
1977 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
1978 {
1979 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001980 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001981 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
1982 }
1983 else {
1984 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
1985 }
1986 }
1987}
1988
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001989sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001990{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001991 my $CodeRef = shift(@_);
1992 my $Tag = shift(@_);
1993 if(not $Tag or not $CodeRef) {
1994 return undef;
1995 }
1996 my $Sp = 0;
1997 if(@_) {
1998 $Sp = shift(@_);
1999 }
2000 my $Start = index(${$CodeRef}, "<$Tag>");
2001 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002002 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002003 my $End = index(${$CodeRef}, "</$Tag>");
2004 if($End!=-1)
2005 {
2006 my $TS = length($Tag)+3;
2007 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2008 substr($Content, 0, $TS-1, ""); # cut start tag
2009 substr($Content, -$TS, $TS, ""); # cut end tag
2010 if(not $Sp)
2011 {
2012 $Content=~s/\A\s+//g;
2013 $Content=~s/\s+\Z//g;
2014 }
2015 if(substr($Content, 0, 1) ne "<") {
2016 $Content = xmlSpecChars_R($Content);
2017 }
2018 return $Content;
2019 }
2020 }
2021 return undef;
2022}
2023
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002024sub getInfo($)
2025{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002026 my $DumpPath = $_[0];
2027 return if(not $DumpPath or not -f $DumpPath);
2028
2029 readTUDump($DumpPath);
2030
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002031 # processing info
2032 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002033
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002034 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002035 setAnonTypedef_All();
2036 }
2037
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002038 getTypeInfo_All();
2039 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002040 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002041 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002042 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002043
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002044 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002045 %LibInfo = ();
2046 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002047 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002048 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002049 %TemplateDecl = ();
2050 %StdCxxTypedef = ();
2051 %MissedTypedef = ();
2052 %Typedef_Tr = ();
2053 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002054 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002055
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002056 # clean cache
2057 delete($Cache{"getTypeAttr"});
2058 delete($Cache{"getTypeDeclId"});
2059
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002060 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002061 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002062 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002063 }
2064 else
2065 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002066 if($BinaryOnly and not $ExtendedCheck)
2067 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002068 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002069 }
2070 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002071 remove_Unused($Version, "Extended");
2072 }
2073 }
2074
2075 if($CheckInfo)
2076 {
2077 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2078 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2079 }
2080
2081 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2082 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002083 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002084 }
2085
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002086 if($Debug) {
2087 # debugMangling($Version);
2088 }
2089}
2090
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002091sub readTUDump($)
2092{
2093 my $DumpPath = $_[0];
2094
2095 open(TU_DUMP, $DumpPath);
2096 local $/ = undef;
2097 my $Content = <TU_DUMP>;
2098 close(TU_DUMP);
2099
2100 unlink($DumpPath);
2101
2102 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002103 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002104
2105 # clean memory
2106 undef $Content;
2107
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002108 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002109
2110 foreach (0 .. $#Lines)
2111 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002112 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002113 { # get a number and attributes of a node
2114 next if(not $NodeType{$2});
2115 $LibInfo{$Version}{"info_type"}{$1}=$2;
2116 $LibInfo{$Version}{"info"}{$1}=$3;
2117 }
2118
2119 # clean memory
2120 delete($Lines[$_]);
2121 }
2122
2123 # clean memory
2124 undef @Lines;
2125}
2126
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002127sub simplifyConstants()
2128{
2129 foreach my $Constant (keys(%{$Constants{$Version}}))
2130 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002131 if(defined $Constants{$Version}{$Constant}{"Header"})
2132 {
2133 my $Value = $Constants{$Version}{$Constant}{"Value"};
2134 if(defined $EnumConstants{$Version}{$Value}) {
2135 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2136 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002137 }
2138 }
2139}
2140
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002141sub simplifyNames()
2142{
2143 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2144 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002145 if($Typedef_Eq{$Version}{$Base}) {
2146 next;
2147 }
2148 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2149 if($#Translations==0)
2150 {
2151 if(length($Translations[0])<=length($Base)) {
2152 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2153 }
2154 }
2155 else
2156 { # select most appropriate
2157 foreach my $Tr (@Translations)
2158 {
2159 if($Base=~/\A\Q$Tr\E/)
2160 {
2161 $Typedef_Eq{$Version}{$Base} = $Tr;
2162 last;
2163 }
2164 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002165 }
2166 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002167 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002168 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002169 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002170 if(not $TypeName) {
2171 next;
2172 }
2173 next if(index($TypeName,"<")==-1);# template instances only
2174 if($TypeName=~/>(::\w+)+\Z/)
2175 { # skip unused types
2176 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002177 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002178 foreach my $Base (sort {length($b)<=>length($a)}
2179 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002180 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002181 next if(not $Base);
2182 next if(index($TypeName,$Base)==-1);
2183 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002184 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002185 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002186 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2187 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2188 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002189 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002190 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2191 {
2192 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2193 {
2194 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2195 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002196 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002197 }
2198 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002199 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002200 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002201 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002202 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002203 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2204 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002205 }
2206}
2207
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002208sub setAnonTypedef_All()
2209{
2210 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2211 {
2212 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2213 {
2214 if(isAnon(getNameByInfo($InfoId))) {
2215 $TypedefToAnon{getTypeId($InfoId)} = 1;
2216 }
2217 }
2218 }
2219}
2220
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002221sub setTemplateParams_All()
2222{
2223 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2224 {
2225 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2226 setTemplateParams($_);
2227 }
2228 }
2229}
2230
2231sub setTemplateParams($)
2232{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002233 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002234 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002235 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002236 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002237 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002238 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002239 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002240 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002241 setTemplateInstParams($_[0], $TmplInst_Id);
2242 }
2243 }
2244
2245 $BasicTemplate{$Version}{$Tid} = $_[0];
2246
2247 if(my $Prms = getTreeAttr_Prms($_[0]))
2248 {
2249 if(my $Valu = getTreeAttr_Valu($Prms))
2250 {
2251 my $Vector = getTreeVec($Valu);
2252 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2253 {
2254 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2255 {
2256 if(my $Name = getNameByInfo($Val))
2257 {
2258 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2259 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2260 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2261 }
2262 else {
2263 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2264 }
2265 }
2266 }
2267 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002268 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002269 }
2270 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002271 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002272 {
2273 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2274 {
2275 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002276 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002277 }
2278 }
2279 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002280}
2281
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002282sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002283{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002284 my ($Tmpl, $Inst) = @_;
2285
2286 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002287 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002288 my ($Params_InfoId, $ElemId) = ();
2289 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2290 $Params_InfoId = $1;
2291 }
2292 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2293 $ElemId = $1;
2294 }
2295 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002296 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002297 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2298 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2299 {
2300 my ($PPos, $PTypeId) = ($1, $2);
2301 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2302 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002303 if($PType eq "template_type_parm") {
2304 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002305 }
2306 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002307 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2308 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002309 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002310 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002311 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002312 else
2313 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002314 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002315 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002317 }
2318 }
2319 }
2320}
2321
2322sub getTypeDeclId($)
2323{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002324 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002325 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002326 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2327 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2328 }
2329 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2330 {
2331 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2332 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2333 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002334 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002335 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002336 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002337}
2338
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002339sub getTypeInfo_All()
2340{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002341 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002342 { # support for GCC < 4.5
2343 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2344 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2345 # FIXME: check GCC versions
2346 addMissedTypes_Pre();
2347 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002348
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002349 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002350 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002351 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2352 if($IType=~/_type\Z/ and $IType ne "function_type"
2353 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002354 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002355 }
2356 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002357
2358 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002359 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002360 "Name" => "...",
2361 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002362 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002363 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002364 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002365
2366 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002367 { # support for GCC < 4.5
2368 addMissedTypes_Post();
2369 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002370
2371 if($ADD_TMPL_INSTANCES)
2372 {
2373 # templates
2374 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2375 {
2376 if(defined $TemplateMap{$Version}{$Tid}
2377 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2378 {
2379 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2380 {
2381 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2382 {
2383 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2384 {
2385 if(my %MAttr = getTypeAttr($MembTypeId))
2386 {
2387 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2388 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2389 }
2390 }
2391 }
2392 }
2393 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2394 {
2395 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2396 {
2397 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2398
2399 if($NBid ne $Bid)
2400 {
2401 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2402 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2403 }
2404 }
2405 }
2406 }
2407 }
2408 }
2409}
2410
2411sub createType($$)
2412{
2413 my ($Attr, $LibVersion) = @_;
2414 my $NewId = ++$MAX_ID;
2415
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002416 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002417 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002418 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002419
2420 return "$NewId";
2421}
2422
2423sub instType($$$)
2424{ # create template instances
2425 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002426
2427 if(not $TypeInfo{$LibVersion}{$Tid}) {
2428 return undef;
2429 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002430 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2431
2432 foreach my $Key (sort keys(%{$Map}))
2433 {
2434 if(my $Val = $Map->{$Key})
2435 {
2436 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2437
2438 if(defined $Attr->{"NameSpace"}) {
2439 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2440 }
2441 foreach (keys(%{$Attr->{"TParam"}})) {
2442 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2443 }
2444 }
2445 else
2446 { # remove absent
2447 # _Traits, etc.
2448 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002449 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002450 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2451 }
2452 foreach (keys(%{$Attr->{"TParam"}}))
2453 {
2454 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2455 delete($Attr->{"TParam"}{$_});
2456 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002457 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002458 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2459 }
2460 }
2461 }
2462 }
2463
2464 my $Tmpl = 0;
2465
2466 if(defined $Attr->{"TParam"})
2467 {
2468 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2469 {
2470 my $PName = $Attr->{"TParam"}{$_}{"name"};
2471
2472 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2473 {
2474 my %Base = get_BaseType($PTid, $LibVersion);
2475
2476 if($Base{"Type"} eq "TemplateParam"
2477 or defined $Base{"Template"})
2478 {
2479 $Tmpl = 1;
2480 last
2481 }
2482 }
2483 }
2484 }
2485
2486 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2487 return "$Id";
2488 }
2489 else
2490 {
2491 if(not $Tmpl) {
2492 delete($Attr->{"Template"});
2493 }
2494
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002495 my $New = createType($Attr, $LibVersion);
2496
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002497 my %EMap = ();
2498 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2499 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2500 }
2501 foreach (keys(%{$Map})) {
2502 $EMap{$_} = $Map->{$_};
2503 }
2504
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002505 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2506 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002507 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002508 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002509 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002510 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002511 {
2512 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2513
2514 if($NBid ne $Bid)
2515 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002516 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2517 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002518 }
2519 }
2520 }
2521
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002522 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002523 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002524 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2525 {
2526 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2527 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2528 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002529 }
2530 }
2531
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002532 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002533 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002534 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2535 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002536 }
2537 }
2538
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002539 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2540 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002541 }
2542
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002543 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002544 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002545}
2546
2547sub addMissedTypes_Pre()
2548{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002549 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002550 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2551 { # detecting missed typedefs
2552 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2553 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002554 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002555 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002556 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002557 if($TypeType eq "Unknown")
2558 { # template_type_parm
2559 next;
2560 }
2561 my $TypeDeclId = getTypeDeclId($TypeId);
2562 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2563 my $TypedefName = getNameByInfo($MissedTDid);
2564 next if(not $TypedefName);
2565 next if($TypedefName eq "__float80");
2566 next if(isAnon($TypedefName));
2567 if(not $TypeDeclId
2568 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002569 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002570 }
2571 }
2572 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002573 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002574 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002575 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002576 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002577 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002578 next;
2579 }
2580 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002581 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002582 if(not $TypedefName) {
2583 next;
2584 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002585 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002586 my %MissedInfo = ( # typedef info
2587 "Name" => $TypedefName,
2588 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002589 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002590 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002591 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002592 my ($H, $L) = getLocation($MissedTDid);
2593 $MissedInfo{"Header"} = $H;
2594 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002595 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002596 { # other types
2597 next;
2598 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002599 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002600 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002601 next;
2602 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002603 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002604 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002605 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002606 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002607 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002608 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002609 next;
2610 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002611 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002612 next;
2613 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002614 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002615 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002616 next;
2617 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002618 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002619 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002620 next;
2621 }
2622 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002623
2624 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2625
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002626 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002627 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002628 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002629 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002630 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002631
2632 # add missed & remove other
2633 $TypeInfo{$Version} = \%AddTypes;
2634 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002635}
2636
2637sub addMissedTypes_Post()
2638{
2639 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2640 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002641 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2642 {
2643 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2644 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2645 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2646 }
2647 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002648 }
2649}
2650
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002651sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002652{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002653 my $TypeId = $_[0];
2654 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2655 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002656 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002657 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002658 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002659}
2660
2661sub getArraySize($$)
2662{
2663 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002664 if(my $Size = getSize($TypeId))
2665 {
2666 my $Elems = $Size/$BYTE_SIZE;
2667 while($BaseName=~s/\s*\[(\d+)\]//) {
2668 $Elems/=$1;
2669 }
2670 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2671 {
2672 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2673 $Elems/=$BasicSize;
2674 }
2675 }
2676 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002677 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002678 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002679}
2680
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002681sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002682{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002683 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002684 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002685 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2686 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002687 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002688 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2689 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2690 if(not $NodeType)
2691 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002692 return ();
2693 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002694 if($NodeType eq "tree_vec")
2695 {
2696 if($Pos!=$#Positions)
2697 { # select last vector of parameters ( ns<P1>::type<P2> )
2698 next;
2699 }
2700 }
2701 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2702 foreach my $P (@Params)
2703 {
2704 if($P eq "") {
2705 return ();
2706 }
2707 elsif($P ne "\@skip\@") {
2708 @TmplParams = (@TmplParams, $P);
2709 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002710 }
2711 }
2712 return @TmplParams;
2713}
2714
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002715sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002716{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002717 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002718 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002719 if(defined $TypeInfo{$Version}{$TypeId}
2720 and $TypeInfo{$Version}{$TypeId}{"Name"})
2721 { # already created
2722 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002723 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002724 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2725 { # incomplete type
2726 return ();
2727 }
2728 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2729
2730 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002731 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002732
2733 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2734 {
2735 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2736 {
2737 if($Info=~/qual[ ]*:/)
2738 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002739 my $NewId = ++$MAX_ID;
2740
2741 $MissedBase{$Version}{$TypeId} = "$NewId";
2742 $MissedBase_R{$Version}{$NewId} = $TypeId;
2743 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2744 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002745 }
2746 }
2747 $TypeAttr{"Type"} = "Typedef";
2748 }
2749 else {
2750 $TypeAttr{"Type"} = getTypeType($TypeId);
2751 }
2752
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002753 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2754 {
2755 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2756 { # local code
2757 return ();
2758 }
2759 }
2760
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002761 if($TypeAttr{"Type"} eq "Unknown") {
2762 return ();
2763 }
2764 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2765 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002766 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002767 if(my $TName = $TypeAttr{"Name"})
2768 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002769 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002770 $TName_Tid{$Version}{$TName} = $TypeId;
2771 return %TypeAttr;
2772 }
2773 else {
2774 return ();
2775 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002776 }
2777 elsif($TypeAttr{"Type"} eq "Array")
2778 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002779 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2780 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002781 return ();
2782 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002783 if(my $Algn = getAlgn($TypeId)) {
2784 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2785 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002786 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002787 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002788 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002789 if(not $BTAttr{"Name"}) {
2790 return ();
2791 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002792 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002793 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002794 if(my $Size = getSize($TypeId)) {
2795 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2796 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002797 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002798 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2799 }
2800 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002801 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002802 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002803 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002804 else
2805 {
2806 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002807 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002808 $TypeAttr{"Name"} = $1."[]".$2;
2809 }
2810 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002811 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002812 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002813 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002814 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002815 if($BTAttr{"Header"}) {
2816 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002817 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002818 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002819 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2820 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002821 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002822 return ();
2823 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002824 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002825 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002826 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002827 if($TypeAttr{"Name"})
2828 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002829 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002830
2831 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2832 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002833 { # NOTE: register only one int: with built-in decl
2834 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2835 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2836 }
2837 }
2838 return %TypeAttr;
2839 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002840 else {
2841 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002842 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002843 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002844 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2845 {
2846 %TypeAttr = getTrivialTypeAttr($TypeId);
2847 if($TypeAttr{"Name"})
2848 {
2849 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2850 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2851 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2852 }
2853 return %TypeAttr;
2854 }
2855 else {
2856 return ();
2857 }
2858 }
2859 elsif($TypeAttr{"Type"} eq "SizeOf")
2860 {
2861 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2862 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2863 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2864 if($TypeAttr{"Name"})
2865 {
2866 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2867 return %TypeAttr;
2868 }
2869 else {
2870 return ();
2871 }
2872 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002873 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002874 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002875 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2876 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002877 return ();
2878 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002879 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002880 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002881 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002882 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002883 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002884 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002885 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002886 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002887 }
2888 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002889 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002890 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002891 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002892 return ();
2893 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002894 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002895 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002896 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002897 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002898 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002899 }
2900 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002901 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002902 {
2903 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002904 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002905 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002906 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002907 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2908 }
2909 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002910 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002911 }
2912 }
2913 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002914 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002915 }
2916 if($TypeAttr{"Type"} eq "Typedef")
2917 {
2918 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002919
2920 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2921 return ();
2922 }
2923
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002924 if(isAnon($TypeAttr{"Name"}))
2925 { # anon typedef to anon type: ._N
2926 return ();
2927 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002928
2929 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2930 { # artificial typedef of "struct X" to "X"
2931 $TypeAttr{"Artificial"} = 1;
2932 }
2933
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002934 if(my $NS = getNameSpace($TypeDeclId))
2935 {
2936 my $TypeName = $TypeAttr{"Name"};
2937 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2938 { # "some_type" is the typedef to "struct some_type" in C++
2939 if($3) {
2940 $TypeAttr{"Name"} = $3."::".$TypeName;
2941 }
2942 }
2943 else
2944 {
2945 $TypeAttr{"NameSpace"} = $NS;
2946 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002947
2948 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2949 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
2950 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002951 if($BTAttr{"NameSpace"}
2952 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002953 { # types like "std::fpos<__mbstate_t>" are
2954 # not covered by typedefs in the TU dump
2955 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002956 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2957 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002958 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002959 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002960 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002961 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002962 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002963 }
2964 }
2965 }
2966 }
2967 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002968 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002969 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002970 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002971 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
2972 { # typedef int*const TYPEDEF; // first
2973 # int foo(TYPEDEF p); // const is optimized out
2974 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
2975 if($BTAttr{"Name"}=~/</)
2976 {
2977 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
2978 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2979 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002980 }
2981 }
2982 }
2983 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
2984 }
2985 if(not $TypeAttr{"Size"})
2986 {
2987 if($TypeAttr{"Type"} eq "Pointer") {
2988 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
2989 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002990 elsif($BTAttr{"Size"}) {
2991 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002992 }
2993 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002994 if(my $Algn = getAlgn($TypeId)) {
2995 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2996 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002997 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002998 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
2999 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003000 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003001 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003002 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003003 { # typedef to "class Class"
3004 # should not be registered in TName_Tid
3005 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3006 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3007 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003008 }
3009 return %TypeAttr;
3010 }
3011}
3012
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003013sub getTreeVec($)
3014{
3015 my %Vector = ();
3016 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3017 {
3018 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3019 { # string length is N-1 because of the null terminator
3020 $Vector{$1} = $2;
3021 }
3022 }
3023 return \%Vector;
3024}
3025
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003026sub get_TemplateParam($$)
3027{
3028 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003029 return () if(not $Type_Id);
3030 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3031 return () if(not $NodeType);
3032 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003033 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003034 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003035 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003036 my $Num = getNodeIntCst($Type_Id);
3037 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003038 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003039 }
3040 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003041 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003042 }
3043 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003044 elsif($NodeType eq "string_cst") {
3045 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003046 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003047 elsif($NodeType eq "tree_vec")
3048 {
3049 my $Vector = getTreeVec($Type_Id);
3050 my @Params = ();
3051 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3052 {
3053 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3054 push(@Params, $P2);
3055 }
3056 }
3057 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003058 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003059 elsif($NodeType eq "parm_decl")
3060 {
3061 (getNameByInfo($Type_Id));
3062 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003063 else
3064 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003065 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003066 my $PName = $ParamAttr{"Name"};
3067 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003068 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003069 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003070 if($PName=~/\>/)
3071 {
3072 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003073 $PName = $Cover;
3074 }
3075 }
3076 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003077 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003078 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3079 # template<typename _Key, typename _Compare = std::less<_Key>
3080 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3081 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3082 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3083 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003084 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003085 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003086 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003087 }
3088}
3089
3090sub cover_stdcxx_typedef($)
3091{
3092 my $TypeName = $_[0];
3093 if(my @Covers = sort {length($a)<=>length($b)}
3094 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3095 { # take the shortest typedef
3096 # FIXME: there may be more than
3097 # one typedefs to the same type
3098 return $Covers[0];
3099 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003100 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003101 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3102 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3103 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003104 if(my $Cover = $Covers[0])
3105 {
3106 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3107 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3108 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003109 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003110 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003111}
3112
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003113sub getNodeIntCst($)
3114{
3115 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003116 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003117 if($EnumMembName_Id{$Version}{$CstId}) {
3118 return $EnumMembName_Id{$Version}{$CstId};
3119 }
3120 elsif((my $Value = getTreeValue($CstId)) ne "")
3121 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003122 if($Value eq "0")
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 "false";
3126 }
3127 else {
3128 return "0";
3129 }
3130 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003131 elsif($Value eq "1")
3132 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003133 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003134 return "true";
3135 }
3136 else {
3137 return "1";
3138 }
3139 }
3140 else {
3141 return $Value;
3142 }
3143 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003144 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003145}
3146
3147sub getNodeStrCst($)
3148{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003149 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3150 {
3151 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003152 {
3153 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3154 { # string length is N-1 because of the null terminator
3155 return substr($1, 0, $2-1);
3156 }
3157 else
3158 { # identifier_node
3159 return substr($1, 0, $2);
3160 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003161 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003162 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003163 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003164}
3165
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003166sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003167{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003168 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003169 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3170 if($Type eq "FieldPtr") {
3171 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3172 }
3173 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3174 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003175 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003176 if($Type eq "MethodPtr")
3177 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003178 if(my $Size = getSize($TypeId))
3179 {
3180 $Size/=$BYTE_SIZE;
3181 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003182 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003183 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003184 if(my $Algn = getAlgn($TypeId)) {
3185 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3186 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003187 # Return
3188 if($Type eq "FieldPtr")
3189 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003190 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003191 if($ReturnAttr{"Name"}) {
3192 $MemPtrName .= $ReturnAttr{"Name"};
3193 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003194 $TypeAttr{"Return"} = $PtrId;
3195 }
3196 else
3197 {
3198 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3199 {
3200 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003201 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3202 if(not $ReturnAttr{"Name"})
3203 { # templates
3204 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003205 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003206 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003207 $TypeAttr{"Return"} = $ReturnTypeId;
3208 }
3209 }
3210 # Class
3211 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3212 {
3213 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003214 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003215 if($Class{"Name"}) {
3216 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3217 }
3218 else {
3219 $MemPtrName .= " (*)";
3220 }
3221 }
3222 else {
3223 $MemPtrName .= " (*)";
3224 }
3225 # Parameters
3226 if($Type eq "FuncPtr"
3227 or $Type eq "MethodPtr")
3228 {
3229 my @ParamTypeName = ();
3230 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3231 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003232 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003233 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003234 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003235 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003236 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3237 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003238 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003239 my $PTypeId = $1;
3240 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003241 if(not $ParamAttr{"Name"})
3242 { # templates (template_type_parm), etc.
3243 return ();
3244 }
3245 if($ParamAttr{"Name"} eq "void") {
3246 last;
3247 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003248 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003249 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003250 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003251 push(@ParamTypeName, $ParamAttr{"Name"});
3252 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003253 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3254 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003255 }
3256 else {
3257 last;
3258 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003259 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003260 else {
3261 last;
3262 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003263 }
3264 }
3265 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3266 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003267 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003268 return %TypeAttr;
3269}
3270
3271sub getTreeTypeName($)
3272{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003273 my $TypeId = $_[0];
3274 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003275 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003276 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003277 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003278 if(my $Name = getNameByInfo($TypeId))
3279 { # bit_size_type
3280 return $Name;
3281 }
3282 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003283 return "unsigned int";
3284 }
3285 else {
3286 return "int";
3287 }
3288 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003289 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003290 return getNameByInfo($1);
3291 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003292 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003293 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003294}
3295
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003296sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003297{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003298 my $Ptd = pointTo($_[0]);
3299 return 0 if(not $Ptd);
3300 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003301 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003302 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3303 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003304 }
3305 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003306 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3307 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003308 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003309 if($InfoT1 eq "pointer_type"
3310 and $InfoT2 eq "function_type") {
3311 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003312 }
3313 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003314 return 0;
3315}
3316
3317sub isMethodPtr($)
3318{
3319 my $Ptd = pointTo($_[0]);
3320 return 0 if(not $Ptd);
3321 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3322 {
3323 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3324 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3325 and $Info=~/ ptrmem /) {
3326 return 1;
3327 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003328 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003329 return 0;
3330}
3331
3332sub isFieldPtr($)
3333{
3334 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3335 {
3336 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3337 and $Info=~/ ptrmem /) {
3338 return 1;
3339 }
3340 }
3341 return 0;
3342}
3343
3344sub pointTo($)
3345{
3346 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3347 {
3348 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3349 return $1;
3350 }
3351 }
3352 return "";
3353}
3354
3355sub getTypeTypeByTypeId($)
3356{
3357 my $TypeId = $_[0];
3358 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3359 {
3360 my $NType = $NodeType{$TType};
3361 if($NType eq "Intrinsic") {
3362 return $NType;
3363 }
3364 elsif(isFuncPtr($TypeId)) {
3365 return "FuncPtr";
3366 }
3367 elsif(isMethodPtr($TypeId)) {
3368 return "MethodPtr";
3369 }
3370 elsif(isFieldPtr($TypeId)) {
3371 return "FieldPtr";
3372 }
3373 elsif($NType ne "Other") {
3374 return $NType;
3375 }
3376 }
3377 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003378}
3379
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003380my %UnQual = (
3381 "r"=>"restrict",
3382 "v"=>"volatile",
3383 "c"=>"const",
3384 "cv"=>"const volatile"
3385);
3386
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003387sub getQual($)
3388{
3389 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003390 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3391 {
3392 my ($Qual, $To) = ();
3393 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3394 $Qual = $UnQual{$1};
3395 }
3396 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3397 $To = $1;
3398 }
3399 if($Qual and $To) {
3400 return ($Qual, $To);
3401 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003402 }
3403 return ();
3404}
3405
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003406sub getQualType($)
3407{
3408 if($_[0] eq "const volatile") {
3409 return "ConstVolatile";
3410 }
3411 return ucfirst($_[0]);
3412}
3413
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003414sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003415{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003416 my $TypeId = $_[0];
3417 my $TypeDeclId = getTypeDeclId($TypeId);
3418 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003419 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003420 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3421 return "Typedef";
3422 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003423 }
3424 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3425 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003426 if(($Qual or $To) and $TypeDeclId
3427 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003428 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003429 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003430 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003431 elsif(not $MissedBase_R{$Version}{$TypeId}
3432 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003433 return "Typedef";
3434 }
3435 elsif($Qual)
3436 { # qualified types
3437 return getQualType($Qual);
3438 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003439
3440 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3441 { # typedef struct { ... } name
3442 $TypeTypedef{$Version}{$TypeId} = $1;
3443 }
3444
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003445 my $TypeType = getTypeTypeByTypeId($TypeId);
3446 if($TypeType eq "Struct")
3447 {
3448 if($TypeDeclId
3449 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3450 return "Template";
3451 }
3452 }
3453 return $TypeType;
3454}
3455
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003456sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003457{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003458 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003459 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003460 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3461 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3462 return 0;
3463 }
3464 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3465 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003466 if(my $TDid = getTypeDeclId($_[0]))
3467 {
3468 if(getTypeId($TDid) eq $_[0]
3469 and getNameByInfo($TDid))
3470 {
3471 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3472 return $1;
3473 }
3474 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003475 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003476 }
3477 }
3478 return 0;
3479}
3480
3481sub selectBaseType($)
3482{
3483 my $TypeId = $_[0];
3484 if(defined $MissedTypedef{$Version}{$TypeId})
3485 { # add missed typedefs
3486 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3487 return ($TypeId, "");
3488 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003489 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003490 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3491 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003492
3493 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3494 my $MB = $MissedBase{$Version}{$TypeId};
3495
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003496 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003497 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003498 and (getTypeId($1) ne $TypeId)
3499 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003500 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003501 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003502 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003503 elsif($MB)
3504 { # add base
3505 return ($MB, "");
3506 }
3507 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003508 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003509 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003510 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003511 elsif($Qual or $To)
3512 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003513 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003514 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003515 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003516 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003517 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003518 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003519 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003520 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003521 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003522 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003523 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003524 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003525 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003526 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003527 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003528 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003529 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003530 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003531 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003532 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003533
3534 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003535}
3536
3537sub getSymbolInfo_All()
3538{
3539 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3540 { # reverse order
3541 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003542 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003543 }
3544 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003545
3546 if($ADD_TMPL_INSTANCES)
3547 {
3548 # templates
3549 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3550 {
3551 my %Map = ();
3552
3553 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3554 {
3555 if(defined $TemplateMap{$Version}{$ClassId})
3556 {
3557 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3558 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3559 }
3560 }
3561 }
3562
3563 if(defined $TemplateMap{$Version}{$Sid})
3564 {
3565 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3566 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3567 }
3568 }
3569
3570 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3571 {
3572 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3573 {
3574 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3575 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3576 }
3577 }
3578 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3579 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3580 }
3581 }
3582 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003583}
3584
3585sub getVarInfo_All()
3586{
3587 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3588 { # reverse order
3589 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003590 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003591 }
3592 }
3593}
3594
3595sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003596 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003597}
3598
3599sub getVarInfo($)
3600{
3601 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003602 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003603 {
3604 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3605 if($NSInfoType and $NSInfoType eq "function_decl") {
3606 return;
3607 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003608 }
3609 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3610 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3611 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3612 delete($SymbolInfo{$Version}{$InfoId});
3613 return;
3614 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003615 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003616 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003617 delete($SymbolInfo{$Version}{$InfoId});
3618 return;
3619 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003620 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3621 delete($SymbolInfo{$Version}{$InfoId});
3622 return;
3623 }
3624 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003625 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3626 {
3627 if($OSgroup eq "windows")
3628 { # cut the offset
3629 $MnglName=~s/\@\d+\Z//g;
3630 }
3631 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3632 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003633 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003634 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003635 { # validate mangled name
3636 delete($SymbolInfo{$Version}{$InfoId});
3637 return;
3638 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003639 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003640 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003641 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003642 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003643 }
3644 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3645 { # non-public global data
3646 delete($SymbolInfo{$Version}{$InfoId});
3647 return;
3648 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003649 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003650 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003651 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003652 if(not defined $TypeInfo{$Version}{$Rid}
3653 or not $TypeInfo{$Version}{$Rid}{"Name"})
3654 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003655 delete($SymbolInfo{$Version}{$InfoId});
3656 return;
3657 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003658 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3659 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003660 if(defined $Val) {
3661 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3662 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003663 }
3664 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003665 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3666 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003667 if(not defined $TypeInfo{$Version}{$ClassId}
3668 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3669 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003670 delete($SymbolInfo{$Version}{$InfoId});
3671 return;
3672 }
3673 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003674 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3675 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003676 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003677 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003678 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003679 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003680 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003681 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003682 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003683 if(not $CheckHeadersOnly)
3684 {
3685 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3686 {
3687 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3688 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3689 {
3690 if(link_symbol($ShortName, $Version, "-Deps"))
3691 { # "const" global data is mangled as _ZL... in the TU dump
3692 # but not mangled when compiling a C shared library
3693 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3694 }
3695 }
3696 }
3697 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003698 if($COMMON_LANGUAGE{$Version} eq "C++")
3699 {
3700 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3701 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003702 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003703 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3704 }
3705 }
3706 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3707 { # try to mangle symbol (link with libraries)
3708 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3709 }
3710 if($OStarget eq "windows")
3711 {
3712 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3713 { # link MS C++ symbols from library with GCC symbols from headers
3714 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3715 }
3716 }
3717 }
3718 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3719 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3720 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003721 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3722 {
3723 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3724 { # non-target symbols
3725 delete($SymbolInfo{$Version}{$InfoId});
3726 return;
3727 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003728 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003729 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3730 {
3731 if(defined $MissedTypedef{$Version}{$Rid})
3732 {
3733 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3734 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3735 }
3736 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003737 }
3738 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003739 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003740 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3741 }
3742 if($ShortName=~/\A(_Z|\?)/) {
3743 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3744 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003745
3746 if($ExtraDump) {
3747 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3748 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003749}
3750
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003751sub isConstType($$)
3752{
3753 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003754 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003755 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003756 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003757 }
3758 return ($Base{"Type"} eq "Const");
3759}
3760
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003761sub getTrivialName($$)
3762{
3763 my ($TypeInfoId, $TypeId) = @_;
3764 my %TypeAttr = ();
3765 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3766 if(not $TypeAttr{"Name"}) {
3767 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3768 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003769 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003770 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003771 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003772 if(isAnon($TypeAttr{"Name"}))
3773 {
3774 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003775 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003776 { # searching for a first not anon scope
3777 if($NSId eq $NameSpaceId) {
3778 last;
3779 }
3780 else
3781 {
3782 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3783 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003784 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003785 last;
3786 }
3787 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003788 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003789 }
3790 }
3791 else
3792 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003793 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003794 {
3795 if($NameSpaceId ne $TypeId) {
3796 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3797 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003798 }
3799 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003800 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003801 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3802 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003803 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003804 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003805 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003806 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003807 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003808 if($TypeAttr{"NameSpace"}) {
3809 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3810 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003811 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003812 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3813 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003814 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003815 if(my @TParams = getTParams($TypeId, "Type")) {
3816 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3817 }
3818 else {
3819 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3820 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003821 }
3822 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3823}
3824
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003825sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003826{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003827 my $TypeId = $_[0];
3828 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003829
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003830 my %TypeAttr = ();
3831
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003832 if($TemplateDecl{$Version}{$TypeId})
3833 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003834 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003835 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003836
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003837 setTypeAccess($TypeId, \%TypeAttr);
3838 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3839 if(isBuiltIn($TypeAttr{"Header"}))
3840 {
3841 delete($TypeAttr{"Header"});
3842 delete($TypeAttr{"Line"});
3843 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003844
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003845 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003846 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3847 if(not $TypeAttr{"Name"}) {
3848 return ();
3849 }
3850 if(not $TypeAttr{"NameSpace"}) {
3851 delete($TypeAttr{"NameSpace"});
3852 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003853
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003854 if($TypeAttr{"Type"} eq "Intrinsic")
3855 {
3856 if(defined $TypeAttr{"Header"})
3857 {
3858 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3859 { # support for SUSE 11.2
3860 # integer_type has srcp dump{1-2}.i
3861 delete($TypeAttr{"Header"});
3862 }
3863 }
3864 }
3865
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003866 my $Tmpl = undef;
3867
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003868 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003869 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003870 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3871
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003872 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003873 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003874 foreach my $Pos (0 .. $#TParams)
3875 {
3876 my $Val = $TParams[$Pos];
3877 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3878
3879 if(not defined $TypeAttr{"Template"})
3880 {
3881 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3882
3883 if($Base{"Type"} eq "TemplateParam"
3884 or defined $Base{"Template"}) {
3885 $TypeAttr{"Template"} = 1;
3886 }
3887 }
3888
3889 if($Tmpl)
3890 {
3891 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3892 {
3893 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3894
3895 if($Val eq $Arg) {
3896 $TypeAttr{"Template"} = 1;
3897 }
3898 }
3899 }
3900 }
3901
3902 if($Tmpl)
3903 {
3904 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3905 {
3906 if($Pos>$#TParams)
3907 {
3908 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3909 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3910 }
3911 }
3912 }
3913 }
3914
3915 if($ADD_TMPL_INSTANCES)
3916 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003917 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003918 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003919 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003920 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003921 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003922 {
3923 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3924 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3925 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003926 }
3927 if(not getTreeAttr_Binf($TypeId))
3928 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003929 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3930 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3931 }
3932 }
3933 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003934 }
3935 }
3936 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003937
3938 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3939
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003940 if(my $Size = getSize($TypeId))
3941 {
3942 $Size = $Size/$BYTE_SIZE;
3943 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003944 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003945 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003946 {
3947 if($ExtraDump)
3948 {
3949 if(not defined $TypeAttr{"Memb"}
3950 and not $Tmpl)
3951 { # declaration only
3952 $TypeAttr{"Forward"} = 1;
3953 }
3954 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003955 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003956
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003957 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003958 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003959 {
3960 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003961 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003962 }
3963 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003964 or $TypeAttr{"Type"} eq "Class")
3965 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003966 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003967 if($Skip) {
3968 return ();
3969 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003970 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003971 if(my $Algn = getAlgn($TypeId)) {
3972 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3973 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003974 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003975
3976 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
3977 {
3978 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003979 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003980 {
3981 if(not isAnon($TypeAttr{"Name"})) {
3982 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
3983 }
3984 }
3985 }
3986
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003987 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003988 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
3989 {
3990 my @Entries = split(/\n/, $VTable);
3991 foreach (1 .. $#Entries)
3992 {
3993 my $Entry = $Entries[$_];
3994 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003995 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003996 }
3997 }
3998 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04003999
4000 if($TypeAttr{"Type"} eq "Enum")
4001 {
4002 if(not $TypeAttr{"NameSpace"})
4003 {
4004 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4005 {
4006 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004007 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004008 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004009 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004010 "Header"=>$TypeAttr{"Header"}
4011 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004012 if(isAnon($TypeAttr{"Name"}))
4013 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004014 if($ExtraDump
4015 or is_target_header($TypeAttr{"Header"}, $Version))
4016 {
4017 %{$Constants{$Version}{$MName}} = (
4018 "Value" => $MVal,
4019 "Header" => $TypeAttr{"Header"}
4020 );
4021 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004022 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004023 }
4024 }
4025 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004026 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004027 {
4028 if(defined $TypedefToAnon{$TypeId}) {
4029 $TypeAttr{"AnonTypedef"} = 1;
4030 }
4031 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004032
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004033 return %TypeAttr;
4034}
4035
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004036sub simplifyVTable($)
4037{
4038 my $Content = $_[0];
4039 if($Content=~s/ \[with (.+)]//)
4040 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4041 if(my @Elems = separate_Params($1, 0, 0))
4042 {
4043 foreach my $Elem (@Elems)
4044 {
4045 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4046 {
4047 my ($Arg, $Val) = ($1, $2);
4048
4049 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4050 $Content=~s/,\s*$Arg\b//g;
4051 }
4052 else {
4053 $Content=~s/\b$Arg\b/$Val/g;
4054 }
4055 }
4056 }
4057 }
4058 }
4059
4060 return $Content;
4061}
4062
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004063sub detect_lang($)
4064{
4065 my $TypeId = $_[0];
4066 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004067 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004068 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004069 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4070 }
4071 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004072 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004073 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004074 while($Fncs)
4075 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004076 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004077 return 1;
4078 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004079 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004080 }
4081 }
4082 return 0;
4083}
4084
4085sub setSpec($$)
4086{
4087 my ($TypeId, $TypeAttr) = @_;
4088 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4089 if($Info=~/\s+spec\s+/) {
4090 $TypeAttr->{"Spec"} = 1;
4091 }
4092}
4093
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004094sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004095{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004096 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004097 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004098 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004099 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004100 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004101 my $Pos = 0;
4102 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4103 {
4104 my ($Access, $BInfoId) = ($1, $2);
4105 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004106
4107 if($ClassId==$TypeId)
4108 { # class A<N>:public A<N-1>
4109 next;
4110 }
4111
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004112 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4113 if(not $CType or $CType eq "template_type_parm"
4114 or $CType eq "typename_type")
4115 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004116 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004117 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004118 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004119 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004120 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4121 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004122 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004123 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4124 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004125 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004126 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004127 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004128 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4129 }
4130 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004131 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004132 }
4133 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004134 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004135}
4136
4137sub getBinfClassId($)
4138{
4139 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
4140 $Info=~/type[ ]*:[ ]*@(\d+) /;
4141 return $1;
4142}
4143
4144sub unmangledFormat($$)
4145{
4146 my ($Name, $LibVersion) = @_;
4147 $Name = uncover_typedefs($Name, $LibVersion);
4148 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4149 $Name=~s/\(\w+\)(\d)/$1/;
4150 return $Name;
4151}
4152
4153sub modelUnmangled($$)
4154{
4155 my ($InfoId, $Compiler) = @_;
4156 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4157 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4158 }
4159 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4160 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4161 $PureSignature = "~".$PureSignature;
4162 }
4163 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4164 {
4165 my (@Params, @ParamTypes) = ();
4166 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4167 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4168 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4169 }
4170 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4171 { # checking parameters
4172 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004173 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004174 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004175 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004176
4177 if($PName eq "this"
4178 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4179 {
4180 next;
4181 }
4182
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004183 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004184 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004185 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004186 }
4187 @ParamTypes = (@ParamTypes, $PTName);
4188 }
4189 if(@ParamTypes) {
4190 $PureSignature .= "(".join(", ", @ParamTypes).")";
4191 }
4192 else
4193 {
4194 if($Compiler eq "MSVC")
4195 {
4196 $PureSignature .= "(void)";
4197 }
4198 else
4199 { # GCC
4200 $PureSignature .= "()";
4201 }
4202 }
4203 $PureSignature = delete_keywords($PureSignature);
4204 }
4205 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4206 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004207 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004208 $PureSignature = $ClassName."::".$PureSignature;
4209 }
4210 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4211 $PureSignature = $NS."::".$PureSignature;
4212 }
4213 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4214 $PureSignature .= " const";
4215 }
4216 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4217 $PureSignature .= " volatile";
4218 }
4219 my $ShowReturn = 0;
4220 if($Compiler eq "MSVC"
4221 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4222 {
4223 $ShowReturn=1;
4224 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004225 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4226 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004227 {
4228 $ShowReturn=1;
4229 }
4230 if($ShowReturn)
4231 { # mangled names for template function specializations include return value
4232 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4233 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004234 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004235 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4236 $PureSignature = $ReturnName." ".$PureSignature;
4237 }
4238 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004239 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004240}
4241
4242sub mangle_symbol($$$)
4243{ # mangling for simple methods
4244 # see gcc-4.6.0/gcc/cp/mangle.c
4245 my ($InfoId, $LibVersion, $Compiler) = @_;
4246 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4247 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4248 }
4249 my $Mangled = "";
4250 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004251 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004252 }
4253 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004254 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004255 }
4256 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4257}
4258
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004259sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004260{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004261 my ($InfoId, $LibVersion) = @_;
4262 return "";
4263}
4264
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004265sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004266{ # see gcc-4.6.0/gcc/cp/mangle.c
4267 my ($InfoId, $LibVersion) = @_;
4268 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004269 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004270 my %Repl = ();# SN_ replacements
4271 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4272 {
4273 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4274 if($MangledClass!~/\AN/) {
4275 $MangledClass = "N".$MangledClass;
4276 }
4277 else {
4278 $MangledClass=~s/E\Z//;
4279 }
4280 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4281 $MangledClass=~s/\AN/NV/;
4282 }
4283 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4284 $MangledClass=~s/\AN/NK/;
4285 }
4286 $Mangled .= $MangledClass;
4287 }
4288 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4289 { # mangled by name due to the absence of structured info
4290 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4291 if($MangledNS!~/\AN/) {
4292 $MangledNS = "N".$MangledNS;
4293 }
4294 else {
4295 $MangledNS=~s/E\Z//;
4296 }
4297 $Mangled .= $MangledNS;
4298 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004299 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004300 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004301 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004302 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004303 foreach (@TPos) {
4304 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4305 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004306 }
4307 elsif($TmplParams)
4308 { # remangling mode
4309 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004310 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004311 }
4312 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4313 $Mangled .= "C1";
4314 }
4315 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4316 $Mangled .= "D0";
4317 }
4318 elsif($ShortName)
4319 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004320 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4321 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004322 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004323 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004324 { # "const" global data is mangled as _ZL...
4325 $Mangled .= "L";
4326 }
4327 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004328 if($ShortName=~/\Aoperator(\W.*)\Z/)
4329 {
4330 my $Op = $1;
4331 $Op=~s/\A[ ]+//g;
4332 if(my $OpMngl = $OperatorMangling{$Op}) {
4333 $Mangled .= $OpMngl;
4334 }
4335 else { # conversion operator
4336 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4337 }
4338 }
4339 else {
4340 $Mangled .= length($ShortName).$ShortName;
4341 }
4342 if(@TParams)
4343 { # templates
4344 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004345 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004346 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4347 }
4348 $Mangled .= "E";
4349 }
4350 if(not $ClassId and @TParams) {
4351 add_substitution($ShortName, \%Repl, 0);
4352 }
4353 }
4354 if($ClassId or $NameSpace) {
4355 $Mangled .= "E";
4356 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004357 if(@TParams)
4358 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004359 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004360 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4361 }
4362 }
4363 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4364 {
4365 my @Params = ();
4366 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4367 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4368 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4369 }
4370 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4371 { # checking parameters
4372 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4373 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4374 }
4375 if(not @Params) {
4376 $Mangled .= "v";
4377 }
4378 }
4379 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4380 $Mangled = write_stdcxx_substitution($Mangled);
4381 if($Mangled eq "_Z") {
4382 return "";
4383 }
4384 return $Mangled;
4385}
4386
4387sub correct_incharge($$$)
4388{
4389 my ($InfoId, $LibVersion, $Mangled) = @_;
4390 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4391 {
4392 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004393 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004394 }
4395 }
4396 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4397 {
4398 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004399 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004400 }
4401 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004402 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004403 }
4404 }
4405 return $Mangled;
4406}
4407
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004408sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004409{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004410 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004411 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004412 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004413 return $Name;
4414 }
4415 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004416 while(my $CPos = find_center($TParams, "<"))
4417 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004418 $TParams = substr($TParams, $CPos);
4419 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004420 if($TParams=~s/\A<(.+)>\Z/$1/) {
4421 $Name=~s/<\Q$TParams\E>\Z//;
4422 }
4423 else
4424 { # error
4425 $TParams = "";
4426 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004427 return ($Name, $TParams);
4428}
4429
4430sub get_sub_ns($)
4431{
4432 my $Name = $_[0];
4433 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004434 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004435 {
4436 push(@NS, substr($Name, 0, $CPos));
4437 $Name = substr($Name, $CPos);
4438 $Name=~s/\A:://;
4439 }
4440 return (join("::", @NS), $Name);
4441}
4442
4443sub mangle_ns($$$)
4444{
4445 my ($Name, $LibVersion, $Repl) = @_;
4446 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4447 {
4448 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4449 $Mangled=~s/\AN(.+)E\Z/$1/;
4450 return $Mangled;
4451
4452 }
4453 else
4454 {
4455 my ($MangledNS, $SubNS) = ("", "");
4456 ($SubNS, $Name) = get_sub_ns($Name);
4457 if($SubNS) {
4458 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4459 }
4460 $MangledNS .= length($Name).$Name;
4461 add_substitution($MangledNS, $Repl, 0);
4462 return $MangledNS;
4463 }
4464}
4465
4466sub mangle_param($$$)
4467{
4468 my ($PTid, $LibVersion, $Repl) = @_;
4469 my ($MPrefix, $Mangled) = ("", "");
4470 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004471 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004472 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004473 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004474 if(not $BaseType_Name) {
4475 return "";
4476 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004477 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004478 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004479 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4480 while($Suffix=~/(&|\*|const)\Z/)
4481 {
4482 if($Suffix=~s/[ ]*&\Z//) {
4483 $MPrefix .= "R";
4484 }
4485 if($Suffix=~s/[ ]*\*\Z//) {
4486 $MPrefix .= "P";
4487 }
4488 if($Suffix=~s/[ ]*const\Z//)
4489 {
4490 if($MPrefix=~/R|P/
4491 or $Suffix=~/&|\*/) {
4492 $MPrefix .= "K";
4493 }
4494 }
4495 if($Suffix=~s/[ ]*volatile\Z//) {
4496 $MPrefix .= "V";
4497 }
4498 #if($Suffix=~s/[ ]*restrict\Z//) {
4499 #$MPrefix .= "r";
4500 #}
4501 }
4502 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4503 $Mangled .= $Token;
4504 }
4505 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4506 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004507 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004508 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004509 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004510 foreach (@TPos) {
4511 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4512 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004513 }
4514 elsif($TmplParams)
4515 { # remangling mode
4516 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004517 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004518 }
4519 my $MangledNS = "";
4520 my ($SubNS, $SName) = get_sub_ns($ShortName);
4521 if($SubNS) {
4522 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4523 }
4524 $MangledNS .= length($SName).$SName;
4525 if(@TParams) {
4526 add_substitution($MangledNS, $Repl, 0);
4527 }
4528 $Mangled .= "N".$MangledNS;
4529 if(@TParams)
4530 { # templates
4531 $Mangled .= "I";
4532 foreach my $TParam (@TParams) {
4533 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4534 }
4535 $Mangled .= "E";
4536 }
4537 $Mangled .= "E";
4538 }
4539 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4540 {
4541 if($BaseType{"Type"} eq "MethodPtr") {
4542 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4543 }
4544 else {
4545 $Mangled .= "PF";
4546 }
4547 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4548 my @Params = keys(%{$BaseType{"Param"}});
4549 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4550 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4551 }
4552 if(not @Params) {
4553 $Mangled .= "v";
4554 }
4555 $Mangled .= "E";
4556 }
4557 elsif($BaseType{"Type"} eq "FieldPtr")
4558 {
4559 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4560 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4561 }
4562 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4563 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4564 {
4565 if($Mangled eq $Optimized)
4566 {
4567 if($ShortName!~/::/)
4568 { # remove "N ... E"
4569 if($MPrefix) {
4570 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4571 }
4572 else {
4573 $Mangled=~s/\AN(.+)E\Z/$1/g;
4574 }
4575 }
4576 }
4577 else {
4578 $Mangled = $Optimized;
4579 }
4580 }
4581 add_substitution($Mangled, $Repl, 1);
4582 return $Mangled;
4583}
4584
4585sub mangle_template_param($$$)
4586{ # types + literals
4587 my ($TParam, $LibVersion, $Repl) = @_;
4588 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4589 return mangle_param($TPTid, $LibVersion, $Repl);
4590 }
4591 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4592 { # class_name<1u>::method(...)
4593 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4594 }
4595 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4596 { # class_name<(signed char)1>::method(...)
4597 return "L".$IntrinsicMangling{$1}.$2."E";
4598 }
4599 elsif($TParam eq "true")
4600 { # class_name<true>::method(...)
4601 return "Lb1E";
4602 }
4603 elsif($TParam eq "false")
4604 { # class_name<true>::method(...)
4605 return "Lb0E";
4606 }
4607 else { # internal error
4608 return length($TParam).$TParam;
4609 }
4610}
4611
4612sub add_substitution($$$)
4613{
4614 my ($Value, $Repl, $Rec) = @_;
4615 if($Rec)
4616 { # subtypes
4617 my @Subs = ($Value);
4618 while($Value=~s/\A(R|P|K)//) {
4619 push(@Subs, $Value);
4620 }
4621 foreach (reverse(@Subs)) {
4622 add_substitution($_, $Repl, 0);
4623 }
4624 return;
4625 }
4626 return if($Value=~/\AS(\d*)_\Z/);
4627 $Value=~s/\AN(.+)E\Z/$1/g;
4628 return if(defined $Repl->{$Value});
4629 return if(length($Value)<=1);
4630 return if($StdcxxMangling{$Value});
4631 # check for duplicates
4632 my $Base = $Value;
4633 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4634 {
4635 my $Num = $Repl->{$Type};
4636 my $Replace = macro_mangle($Num);
4637 $Base=~s/\Q$Replace\E/$Type/;
4638 }
4639 if(my $OldNum = $Repl->{$Base})
4640 {
4641 $Repl->{$Value} = $OldNum;
4642 return;
4643 }
4644 my @Repls = sort {$b<=>$a} values(%{$Repl});
4645 if(@Repls) {
4646 $Repl->{$Value} = $Repls[0]+1;
4647 }
4648 else {
4649 $Repl->{$Value} = -1;
4650 }
4651 # register duplicates
4652 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004653 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004654 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4655 {
4656 next if($Base eq $Type);
4657 my $Num = $Repl->{$Type};
4658 my $Replace = macro_mangle($Num);
4659 $Base=~s/\Q$Type\E/$Replace/;
4660 $Repl->{$Base} = $Repl->{$Value};
4661 }
4662}
4663
4664sub macro_mangle($)
4665{
4666 my $Num = $_[0];
4667 if($Num==-1) {
4668 return "S_";
4669 }
4670 else
4671 {
4672 my $Code = "";
4673 if($Num<10)
4674 { # S0_, S1_, S2_, ...
4675 $Code = $Num;
4676 }
4677 elsif($Num>=10 and $Num<=35)
4678 { # SA_, SB_, SC_, ...
4679 $Code = chr(55+$Num);
4680 }
4681 else
4682 { # S10_, S11_, S12_
4683 $Code = $Num-26; # 26 is length of english alphabet
4684 }
4685 return "S".$Code."_";
4686 }
4687}
4688
4689sub write_stdcxx_substitution($)
4690{
4691 my $Mangled = $_[0];
4692 if($StdcxxMangling{$Mangled}) {
4693 return $StdcxxMangling{$Mangled};
4694 }
4695 else
4696 {
4697 my @Repls = keys(%StdcxxMangling);
4698 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4699 foreach my $MangledType (@Repls)
4700 {
4701 my $Replace = $StdcxxMangling{$MangledType};
4702 #if($Mangled!~/$Replace/) {
4703 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4704 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4705 #}
4706 }
4707 }
4708 return $Mangled;
4709}
4710
4711sub write_substitution($$)
4712{
4713 my ($Mangled, $Repl) = @_;
4714 if(defined $Repl->{$Mangled}
4715 and my $MnglNum = $Repl->{$Mangled}) {
4716 $Mangled = macro_mangle($MnglNum);
4717 }
4718 else
4719 {
4720 my @Repls = keys(%{$Repl});
4721 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4722 # FIXME: how to apply replacements? by num or by pos
4723 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4724 foreach my $MangledType (@Repls)
4725 {
4726 my $Replace = macro_mangle($Repl->{$MangledType});
4727 if($Mangled!~/$Replace/) {
4728 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4729 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4730 }
4731 }
4732 }
4733 return $Mangled;
4734}
4735
4736sub delete_keywords($)
4737{
4738 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004739 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004740 return $TypeName;
4741}
4742
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004743sub uncover_typedefs($$)
4744{
4745 my ($TypeName, $LibVersion) = @_;
4746 return "" if(not $TypeName);
4747 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4748 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4749 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004750 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004751 while($TypeName_New ne $TypeName_Pre)
4752 {
4753 $TypeName_Pre = $TypeName_New;
4754 my $TypeName_Copy = $TypeName_New;
4755 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004756 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004757 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004758 if(not $Intrinsic_Keywords{$1}) {
4759 $Words{$1} = 1;
4760 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004761 }
4762 foreach my $Word (keys(%Words))
4763 {
4764 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4765 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004766 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004767 if($BaseType_Name=~/\([\*]+\)/)
4768 { # FuncPtr
4769 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4770 {
4771 my $Type_Suffix = $1;
4772 $TypeName_New = $BaseType_Name;
4773 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004774 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004775 }
4776 }
4777 }
4778 else
4779 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004780 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004781 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004782 }
4783 }
4784 }
4785 }
4786 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4787}
4788
4789sub isInternal($)
4790{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004791 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4792 {
4793 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4794 {
4795 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4796 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4797 return 1;
4798 }
4799 }
4800 }
4801 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004802}
4803
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004804sub getDataVal($$)
4805{
4806 my ($InfoId, $TypeId) = @_;
4807 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4808 {
4809 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4810 {
4811 if(defined $LibInfo{$Version}{"info_type"}{$1}
4812 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004813 {
4814 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004815 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004816 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4817 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004818 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004819 if(my $Addr = getTreeAttr_Op($1)) {
4820 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004821 }
4822 }
4823 }
4824 }
4825 else {
4826 return getInitVal($1, $TypeId);
4827 }
4828 }
4829 }
4830 return undef;
4831}
4832
4833sub getInitVal($$)
4834{
4835 my ($InfoId, $TypeId) = @_;
4836 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4837 {
4838 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4839 {
4840 if($InfoType eq "integer_cst")
4841 {
4842 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004843 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004844 { # characters
4845 $Val = chr($Val);
4846 }
4847 return $Val;
4848 }
4849 elsif($InfoType eq "string_cst") {
4850 return getNodeStrCst($InfoId);
4851 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004852 elsif($InfoType eq "var_decl")
4853 {
4854 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4855 return $Name;
4856 }
4857 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004858 }
4859 }
4860 return undef;
4861}
4862
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004863sub set_Class_And_Namespace($)
4864{
4865 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004866 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004867 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004868 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004869 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004870 my $NSInfoId = $1;
4871 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4872 {
4873 if($InfoType eq "namespace_decl") {
4874 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4875 }
4876 elsif($InfoType eq "record_type") {
4877 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4878 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004879 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004880 }
4881 }
4882 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4883 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004884 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004885 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004886 { # skip
4887 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004888 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004889 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004890
4891 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004892}
4893
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004894sub debugMangling($)
4895{
4896 my $LibVersion = $_[0];
4897 my %Mangled = ();
4898 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4899 {
4900 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4901 {
4902 if($Mngl=~/\A(_Z|\?)/) {
4903 $Mangled{$Mngl}=$InfoId;
4904 }
4905 }
4906 }
4907 translateSymbols(keys(%Mangled), $LibVersion);
4908 foreach my $Mngl (keys(%Mangled))
4909 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004910 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4911 my $U2 = $tr_name{$Mngl};
4912 if($U1 ne $U2) {
4913 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004914 }
4915 }
4916}
4917
4918sub linkSymbol($)
4919{ # link symbols from shared libraries
4920 # with the symbols from header files
4921 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004922 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004923 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004924 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4925 or $EMERGENCY_MODE_48)
4926 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4927 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
4928 # GCC 4.8 doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004929 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004930 {
4931 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4932 return correct_incharge($InfoId, $Version, $Mangled);
4933 }
4934 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004935 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004936 or not $BinaryOnly
4937 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004938 { # 1. --headers-only mode
4939 # 2. not mangled src-only symbols
4940 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4941 return $Mangled;
4942 }
4943 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004944 }
4945 return "";
4946}
4947
4948sub setLanguage($$)
4949{
4950 my ($LibVersion, $Lang) = @_;
4951 if(not $UserLang) {
4952 $COMMON_LANGUAGE{$LibVersion} = $Lang;
4953 }
4954}
4955
4956sub getSymbolInfo($)
4957{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004958 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004959 if(isInternal($InfoId)) {
4960 return;
4961 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004962 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
4963 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004964 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
4965 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004966 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004967 return;
4968 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004969 setFuncAccess($InfoId);
4970 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004971 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
4972 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004973 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004974 return;
4975 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004976
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004977 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004978 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004979 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004980 if(not defined $TypeInfo{$Version}{$Return}
4981 or not $TypeInfo{$Version}{$Return}{"Name"})
4982 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004983 delete($SymbolInfo{$Version}{$InfoId});
4984 return;
4985 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004986 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004987 }
4988 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
4989 {
4990 if(defined $MissedTypedef{$Version}{$Rid})
4991 {
4992 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
4993 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
4994 }
4995 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004996 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004997 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
4998 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004999 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005000 my $Orig = getFuncOrig($InfoId);
5001 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005002 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5003 {
5004 delete($SymbolInfo{$Version}{$InfoId});
5005 return;
5006 }
5007
5008 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005009 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005010 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005011 return;
5012 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005013
5014 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005015 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005016 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5017
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005018 my @TParams = getTParams($Orig, "Func");
5019 if(not @TParams)
5020 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005021 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005022 return;
5023 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005024 foreach my $Pos (0 .. $#TParams)
5025 {
5026 my $Val = $TParams[$Pos];
5027 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5028
5029 if($Tmpl)
5030 {
5031 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5032 {
5033 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5034 }
5035 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005036 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005037
5038 if($Tmpl)
5039 {
5040 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5041 {
5042 if($Pos>$#TParams)
5043 {
5044 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5045 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5046 }
5047 }
5048 }
5049
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005050 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5051 { # operator<< <T>, operator>> <T>
5052 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5053 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005054 if(@TParams) {
5055 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5056 }
5057 else {
5058 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5059 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005060 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005061 }
5062 else
5063 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005064 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005065 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005066 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5067 {
5068 if($OSgroup eq "windows")
5069 { # cut the offset
5070 $MnglName=~s/\@\d+\Z//g;
5071 }
5072 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5073
5074 # NOTE: mangling of some symbols may change depending on GCC version
5075 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5076 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5077 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005078
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005079 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005080 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005081 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005082 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005083 return;
5084 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005085 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005086 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005087 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005088 if($Skip)
5089 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005090 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005091 return;
5092 }
5093 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005094 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5095 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5096 }
5097
5098 if(set_Class_And_Namespace($InfoId))
5099 {
5100 delete($SymbolInfo{$Version}{$InfoId});
5101 return;
5102 }
5103
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005104 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5105 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005106 if(not defined $TypeInfo{$Version}{$ClassId}
5107 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5108 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005109 delete($SymbolInfo{$Version}{$InfoId});
5110 return;
5111 }
5112 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005113 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5114 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005115 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005116 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005117 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005118 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005119 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005120 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005121 }
5122 if($COMMON_LANGUAGE{$Version} eq "C++")
5123 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005124 # C++ or --headers-only mode
5125 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005126 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005127 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5128 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005129 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005130 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005131 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005132 if(my $Mangled = linkSymbol($InfoId)) {
5133 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005134 }
5135 }
5136 if($OStarget eq "windows")
5137 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005138 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005139 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005140 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005141 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005142 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005143 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005144 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005145 }
5146 }
5147 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005148 else
5149 { # not mangled in C
5150 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5151 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005152 if(not $CheckHeadersOnly
5153 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5154 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5155 {
5156 my $Incorrect = 0;
5157
5158 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5159 {
5160 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5161 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5162 { # mangled in the TU dump, but not mangled in the library
5163 $Incorrect = 1;
5164 }
5165 }
5166 else
5167 {
5168 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5169 { # all C++ functions are not mangled in the TU dump
5170 $Incorrect = 1;
5171 }
5172 }
5173 if($Incorrect)
5174 {
5175 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5176 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5177 }
5178 }
5179 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005180 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005181 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005182 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005183 return;
5184 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005185 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005186 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005187 { # identify virtual and pure virtual functions
5188 # NOTE: constructors cannot be virtual
5189 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5190 # in the TU dump, so taking it from the original symbol
5191 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5192 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5193 { # NOTE: D2 destructors are not present in a v-table
5194 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5195 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005196 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005197 if(isInline($InfoId)) {
5198 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005199 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005200 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005201 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5202 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005203 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5204 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005205 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005206 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005207 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005208 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005209 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005210 }
5211 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005212 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5213 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005214 if(not $ExtraDump)
5215 {
5216 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5217 { # non-target symbols
5218 delete($SymbolInfo{$Version}{$InfoId});
5219 return;
5220 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005221 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005222 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005223 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5224 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5225 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5226 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005227 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005228 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5229 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005230 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005231 return;
5232 }
5233 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005234 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005235 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005236 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005237 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005238 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005239 return;
5240 }
5241 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005242 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005243 }
5244 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005245 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5246 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5247 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005248 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005249 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5250 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005251 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005252 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005253 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005254 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005255 }
5256 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005257 if(getFuncLink($InfoId) eq "Static") {
5258 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005259 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005260 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5261 {
5262 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5263 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005264 if($Unmangled=~/\.\_\d/)
5265 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005266 delete($SymbolInfo{$Version}{$InfoId});
5267 return;
5268 }
5269 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005270 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005271
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005272 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5273 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005274 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005275 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5276 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005277 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005278
5279 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5280 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5281 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005282
5283 if($ExtraDump) {
5284 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5285 }
5286}
5287
5288sub guessHeader($)
5289{
5290 my $InfoId = $_[0];
5291 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5292 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5293 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5294 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5295 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5296 {
5297 if(get_filename($HPath) eq $Header)
5298 {
5299 my $HDir = get_filename(get_dirname($HPath));
5300 if($HDir ne "include"
5301 and $HDir=~/\A[a-z]+\Z/i) {
5302 return join_P($HDir, $Header);
5303 }
5304 }
5305 }
5306 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005307}
5308
5309sub isInline($)
5310{ # "body: undefined" in the tree
5311 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005312 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5313 {
5314 if($Info=~/ undefined /i) {
5315 return 0;
5316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005317 }
5318 return 1;
5319}
5320
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005321sub hasThrow($)
5322{
5323 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5324 {
5325 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5326 return getTreeAttr_Unql($1, "unql");
5327 }
5328 }
5329 return 1;
5330}
5331
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005332sub getTypeId($)
5333{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005334 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5335 {
5336 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5337 return $1;
5338 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005339 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005340 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005341}
5342
5343sub setTypeMemb($$)
5344{
5345 my ($TypeId, $TypeAttr) = @_;
5346 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005347 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005348 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005349 if($TypeType eq "Enum")
5350 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005351 my $MInfoId = getTreeAttr_Csts($TypeId);
5352 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005353 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005354 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5355 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005356 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005357 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5358 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005359 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005360 }
5361 }
5362 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5363 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005364 my $MInfoId = getTreeAttr_Flds($TypeId);
5365 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005366 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005367 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5368 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005369 if(not $IType or $IType ne "field_decl")
5370 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005371
5372 if($IType eq "var_decl")
5373 { # static field
5374 $StaticFields = 1;
5375 }
5376
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005377 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005378 next;
5379 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005380 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005381 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005382 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005383 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005384 }
5385 if(not $StructMembName)
5386 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005387 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005388 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005389 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005390 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5391 if(isAnon($UnnamedTName))
5392 { # rename unnamed fields to unnamed0, unnamed1, ...
5393 $StructMembName = "unnamed".($UnnamedPos++);
5394 }
5395 }
5396 }
5397 if(not $StructMembName)
5398 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005399 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005400 next;
5401 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005402 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005403 if(defined $MissedTypedef{$Version}{$MembTypeId})
5404 {
5405 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5406 $MembTypeId = $AddedTid;
5407 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005408 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005409
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005410 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5411 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005412 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005413 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005414 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5415 }
5416 if($MInfo=~/spec:\s*mutable /)
5417 { # mutable fields
5418 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005419 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005420 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005421 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5422 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005423 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005424 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005425 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005426 }
5427 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005428 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005429 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5430 { # template
5431 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5432 }
5433 else {
5434 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5435 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005436 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005437
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005438 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005439 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005440 }
5441 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005442
5443 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005444}
5445
5446sub setFuncParams($)
5447{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005448 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005449 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005450
5451 my $FType = getFuncType($InfoId);
5452
5453 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005454 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005455 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5456 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005457 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005458 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005459 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5460 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005461 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005462 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5463 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005464 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005465 else
5466 { # skip
5467 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005468 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005469 # skip "this"-parameter
5470 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005471 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005472 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005473 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005474 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005475 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5476 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5477 if(not $ParamName)
5478 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005479 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005480 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005481 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5482 {
5483 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5484 $ParamTypeId = $AddedTid;
5485 }
5486 }
5487 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005488 if(not $PType or $PType eq "Unknown") {
5489 return 1;
5490 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005491 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005492 if(not $PTName) {
5493 return 1;
5494 }
5495 if($PTName eq "void") {
5496 last;
5497 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005498 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005499 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005500 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005501 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005502 $ParamInfoId = getNextElem($ParamInfoId);
5503 next;
5504 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005505 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005506
5507 if(my %Base = get_BaseType($ParamTypeId, $Version))
5508 {
5509 if(defined $Base{"Template"}) {
5510 return 1;
5511 }
5512 }
5513
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005514 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005515 if(my $Algn = getAlgn($ParamInfoId)) {
5516 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5517 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005518 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5519 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005520 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005521 }
5522 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005523 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005524 if($ParamName ne "this" or $FType ne "Method") {
5525 $PPos += 1;
5526 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005527 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005528 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005529 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005530 }
5531 return 0;
5532}
5533
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005534sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005535{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005536 my ($InfoId, $Vtt_Pos) = @_;
5537 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005538 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005539 my $FType = getFuncType($InfoId);
5540
5541 if($FType eq "Method")
5542 {
5543 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005544 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005545 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005546 if(not $ParamListElemId)
5547 { # foo(...)
5548 return 1;
5549 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005550 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005551 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005552 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005553 { # actual params: may differ from formal args
5554 # formal int*const
5555 # actual: int*
5556 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005557 {
5558 $Vtt_Pos=-1;
5559 $ParamListElemId = getNextElem($ParamListElemId);
5560 next;
5561 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005562 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5563 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005564 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005565 $HaveVoid = 1;
5566 last;
5567 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005568 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005569 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005570 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5571 {
5572 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5573 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5574 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005575 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005576 }
5577 }
5578 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5579 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005580 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005581 { # params
5582 if($OldId ne $ParamTypeId)
5583 {
5584 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5585 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5586
5587 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5588 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5589 }
5590 }
5591 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005592 }
5593 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005594 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005595 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005596 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5597 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005598 if($PurpType eq "nop_expr")
5599 { # func ( const char* arg = (const char*)(void*)0 )
5600 $PurpId = getTreeAttr_Op($PurpId);
5601 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005602 my $Val = getInitVal($PurpId, $ParamTypeId);
5603 if(defined $Val) {
5604 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5605 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005606 }
5607 }
5608 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005609 if($Pos!=0 or $FType ne "Method") {
5610 $PPos += 1;
5611 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005612 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005613 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005614 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005615}
5616
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005617sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005618{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005619 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5620 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005621 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5622 return $1;
5623 }
5624 }
5625 return "";
5626}
5627
5628sub getTreeAttr_Chain($)
5629{
5630 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5631 {
5632 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5633 return $1;
5634 }
5635 }
5636 return "";
5637}
5638
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005639sub getTreeAttr_Unql($)
5640{
5641 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5642 {
5643 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5644 return $1;
5645 }
5646 }
5647 return "";
5648}
5649
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005650sub getTreeAttr_Scpe($)
5651{
5652 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5653 {
5654 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5655 return $1;
5656 }
5657 }
5658 return "";
5659}
5660
5661sub getTreeAttr_Type($)
5662{
5663 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5664 {
5665 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5666 return $1;
5667 }
5668 }
5669 return "";
5670}
5671
5672sub getTreeAttr_Name($)
5673{
5674 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5675 {
5676 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5677 return $1;
5678 }
5679 }
5680 return "";
5681}
5682
5683sub getTreeAttr_Mngl($)
5684{
5685 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5686 {
5687 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5688 return $1;
5689 }
5690 }
5691 return "";
5692}
5693
5694sub getTreeAttr_Prms($)
5695{
5696 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5697 {
5698 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5699 return $1;
5700 }
5701 }
5702 return "";
5703}
5704
5705sub getTreeAttr_Fncs($)
5706{
5707 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5708 {
5709 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5710 return $1;
5711 }
5712 }
5713 return "";
5714}
5715
5716sub getTreeAttr_Csts($)
5717{
5718 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5719 {
5720 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5721 return $1;
5722 }
5723 }
5724 return "";
5725}
5726
5727sub getTreeAttr_Purp($)
5728{
5729 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5730 {
5731 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5732 return $1;
5733 }
5734 }
5735 return "";
5736}
5737
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005738sub getTreeAttr_Op($)
5739{
5740 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5741 {
5742 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5743 return $1;
5744 }
5745 }
5746 return "";
5747}
5748
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005749sub getTreeAttr_Valu($)
5750{
5751 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5752 {
5753 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5754 return $1;
5755 }
5756 }
5757 return "";
5758}
5759
5760sub getTreeAttr_Flds($)
5761{
5762 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5763 {
5764 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5765 return $1;
5766 }
5767 }
5768 return "";
5769}
5770
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005771sub getTreeAttr_Binf($)
5772{
5773 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5774 {
5775 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5776 return $1;
5777 }
5778 }
5779 return "";
5780}
5781
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005782sub getTreeAttr_Args($)
5783{
5784 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5785 {
5786 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005787 return $1;
5788 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005789 }
5790 return "";
5791}
5792
5793sub getTreeValue($)
5794{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005795 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5796 {
5797 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5798 return $1;
5799 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005800 }
5801 return "";
5802}
5803
5804sub getTreeAccess($)
5805{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005806 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005807 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005808 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5809 {
5810 my $Access = $1;
5811 if($Access eq "prot") {
5812 return "protected";
5813 }
5814 elsif($Access eq "priv") {
5815 return "private";
5816 }
5817 }
5818 elsif($Info=~/ protected /)
5819 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005820 return "protected";
5821 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005822 elsif($Info=~/ private /)
5823 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005824 return "private";
5825 }
5826 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005827 return "public";
5828}
5829
5830sub setFuncAccess($)
5831{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005832 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005833 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005834 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005835 }
5836 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005837 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005838 }
5839}
5840
5841sub setTypeAccess($$)
5842{
5843 my ($TypeId, $TypeAttr) = @_;
5844 my $Access = getTreeAccess($TypeId);
5845 if($Access eq "protected") {
5846 $TypeAttr->{"Protected"} = 1;
5847 }
5848 elsif($Access eq "private") {
5849 $TypeAttr->{"Private"} = 1;
5850 }
5851}
5852
5853sub setFuncKind($)
5854{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005855 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5856 {
5857 if($Info=~/pseudo tmpl/) {
5858 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5859 }
5860 elsif($Info=~/ constructor /) {
5861 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5862 }
5863 elsif($Info=~/ destructor /) {
5864 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5865 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005866 }
5867}
5868
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005869sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005870{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005871 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5872 {
5873 if($Info=~/spec[ ]*:[ ]*pure /) {
5874 return "PureVirt";
5875 }
5876 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5877 return "Virt";
5878 }
5879 elsif($Info=~/ pure\s+virtual /)
5880 { # support for old GCC versions
5881 return "PureVirt";
5882 }
5883 elsif($Info=~/ virtual /)
5884 { # support for old GCC versions
5885 return "Virt";
5886 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005887 }
5888 return "";
5889}
5890
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005891sub getFuncLink($)
5892{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005893 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5894 {
5895 if($Info=~/link[ ]*:[ ]*static /) {
5896 return "Static";
5897 }
5898 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005899 return $1;
5900 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005901 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005902 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005903}
5904
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005905sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005906{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005907 my ($Symbol, $LibVersion) = @_;
5908 return "" if(not $Symbol or not $LibVersion);
5909 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5910 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005911 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005912 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5913 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5914 }
5915 }
5916 if($NS)
5917 {
5918 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5919 return $NS;
5920 }
5921 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005922 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005923 while($NS=~s/::[^:]+\Z//)
5924 {
5925 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5926 return $NS;
5927 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005928 }
5929 }
5930 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005931
5932 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005933}
5934
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005935sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005936{
5937 my ($TypeName, $LibVersion) = @_;
5938 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005939 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005940 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005941 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5942 return $NS;
5943 }
5944 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005945 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005946 while($NS=~s/::[^:]+\Z//)
5947 {
5948 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5949 return $NS;
5950 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005951 }
5952 }
5953 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005954 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005955}
5956
5957sub getNameSpace($)
5958{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005959 my $InfoId = $_[0];
5960 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005961 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005962 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005963 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005964 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005965 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005966 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
5967 {
5968 my $NameSpace = getTreeStr($1);
5969 if($NameSpace eq "::")
5970 { # global namespace
5971 return "";
5972 }
5973 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
5974 $NameSpace = $BaseNameSpace."::".$NameSpace;
5975 }
5976 $NestedNameSpaces{$Version}{$NameSpace} = 1;
5977 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005978 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005979 else {
5980 return "";
5981 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005982 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005983 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005984 { # inside data type
5985 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
5986 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005987 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005988 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005989 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005990 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005991}
5992
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005993sub getEnumMembVal($)
5994{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005995 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005996 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005997 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
5998 {
5999 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6000 {
6001 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6002 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6003 return getTreeValue($1);
6004 }
6005 else
6006 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6007 return getTreeValue($1);
6008 }
6009 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006010 }
6011 }
6012 return "";
6013}
6014
6015sub getSize($)
6016{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006017 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6018 {
6019 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6020 return getTreeValue($1);
6021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006022 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006023 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006024}
6025
6026sub getAlgn($)
6027{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006028 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6029 {
6030 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6031 return $1;
6032 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006033 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006034 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006035}
6036
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006037sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006038{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006039 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6040 {
6041 if($Info=~/ bitfield /) {
6042 return getSize($_[0]);
6043 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006044 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006045 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006046}
6047
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006048sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006049{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006050 if(my $Chan = getTreeAttr_Chan($_[0])) {
6051 return $Chan;
6052 }
6053 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6054 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006055 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006056 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006057}
6058
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006059sub registerHeader($$)
6060{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006061 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006062 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006063 return "";
6064 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006065 if(is_abs($Header) and not -f $Header)
6066 { # incorrect absolute path
6067 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006068 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006069 if(skipHeader($Header, $LibVersion))
6070 { # skip
6071 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006072 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006073 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6074 {
6075 detect_header_includes($Header_Path, $LibVersion);
6076
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006077 if(defined $Tolerance and $Tolerance=~/3/)
6078 { # 3 - skip headers that include non-Linux headers
6079 if($OSgroup ne "windows")
6080 {
6081 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6082 {
6083 if(specificHeader($Inc, "windows")) {
6084 return "";
6085 }
6086 }
6087 }
6088 }
6089
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006090 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6091 { # redirect
6092 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6093 or skipHeader($RHeader_Path, $LibVersion))
6094 { # skip
6095 return "";
6096 }
6097 $Header_Path = $RHeader_Path;
6098 }
6099 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6100 { # skip
6101 return "";
6102 }
6103
6104 if(my $HName = get_filename($Header_Path))
6105 { # register
6106 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6107 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6108 }
6109
6110 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6111 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006112 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006113 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006114 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006115 }
6116
6117 if($CheckHeadersOnly
6118 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6119 { # /usr/include/c++/4.6.1/...
6120 $STDCXX_TESTING = 1;
6121 }
6122
6123 return $Header_Path;
6124 }
6125 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006126}
6127
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006128sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006129{
6130 my ($Dir, $WithDeps, $LibVersion) = @_;
6131 $Dir=~s/[\/\\]+\Z//g;
6132 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006133 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006134
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006135 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006136 if($WithDeps)
6137 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006138 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6139 return;
6140 }
6141 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6142 $Mode = "DepsOnly";
6143 }
6144 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006145 else
6146 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006147 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6148 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6149 return;
6150 }
6151 }
6152 $Header_Dependency{$LibVersion}{$Dir} = 1;
6153 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6154 if($Mode eq "DepsOnly")
6155 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006156 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006157 $Header_Dependency{$LibVersion}{$Path} = 1;
6158 }
6159 return;
6160 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006161 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006162 {
6163 if($WithDeps)
6164 {
6165 my $SubDir = $Path;
6166 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6167 { # register all sub directories
6168 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6169 }
6170 }
6171 next if(is_not_header($Path));
6172 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006173 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006174 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006175 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6176 }
6177 }
6178 if(get_filename($Dir) eq "include")
6179 { # search for "lib/include/" directory
6180 my $LibDir = $Dir;
6181 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006182 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006183 }
6184 }
6185}
6186
6187sub parse_redirect($$$)
6188{
6189 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006190 my @Errors = ();
6191 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6192 push(@Errors, $1);
6193 }
6194 my $Redirect = "";
6195 foreach (@Errors)
6196 {
6197 s/\s{2,}/ /g;
6198 if(/(only|must\ include
6199 |update\ to\ include
6200 |replaced\ with
6201 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006202 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006203 {
6204 $Redirect = $2;
6205 last;
6206 }
6207 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6208 {
6209 $Redirect = $2;
6210 last;
6211 }
6212 elsif(/this\ header\ should\ not\ be\ used
6213 |programs\ should\ not\ directly\ include
6214 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6215 |is\ not\ supported\ API\ for\ general\ use
6216 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006217 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006218 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6219 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6220 }
6221 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006222 if($Redirect)
6223 {
6224 $Redirect=~s/\A<//g;
6225 $Redirect=~s/>\Z//g;
6226 }
6227 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006228}
6229
6230sub parse_includes($$)
6231{
6232 my ($Content, $Path) = @_;
6233 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006234 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006235 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006236 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006237 my $Method = substr($Header, 0, 1, "");
6238 substr($Header, length($Header)-1, 1, "");
6239 $Header = path_format($Header, $OSgroup);
6240 if($Method eq "\"" or is_abs($Header))
6241 {
6242 if(-e join_P(get_dirname($Path), $Header))
6243 { # relative path exists
6244 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006245 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006246 else
6247 { # include "..." that doesn't exist is equal to include <...>
6248 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006249 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006250 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006251 else {
6252 $Includes{$Header} = 1;
6253 }
6254 }
6255 if($ExtraInfo)
6256 {
6257 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6258 { # FT_FREETYPE_H
6259 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006260 }
6261 }
6262 return \%Includes;
6263}
6264
6265sub ignore_path($)
6266{
6267 my $Path = $_[0];
6268 if($Path=~/\~\Z/)
6269 {# skipping system backup files
6270 return 1;
6271 }
6272 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6273 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6274 return 1;
6275 }
6276 return 0;
6277}
6278
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006279sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006280{
6281 my ($ArrRef, $W) = @_;
6282 return if(length($W)<2);
6283 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6284}
6285
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006286sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006287{
6288 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006289
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006290 $H1=~s/\.[a-z]+\Z//ig;
6291 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006292
6293 my $Hname1 = get_filename($H1);
6294 my $Hname2 = get_filename($H2);
6295 my $HDir1 = get_dirname($H1);
6296 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006297 my $Dirname1 = get_filename($HDir1);
6298 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006299
6300 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6301 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6302
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006303 if($_[0] eq $_[1]
6304 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006305 return 0;
6306 }
6307 elsif($H1=~/\A\Q$H2\E/) {
6308 return 1;
6309 }
6310 elsif($H2=~/\A\Q$H1\E/) {
6311 return -1;
6312 }
6313 elsif($HDir1=~/\Q$Hname1\E/i
6314 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006315 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006316 return -1;
6317 }
6318 elsif($HDir2=~/\Q$Hname2\E/i
6319 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006320 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006321 return 1;
6322 }
6323 elsif($Hname1=~/\Q$Dirname1\E/i
6324 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006325 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006326 return -1;
6327 }
6328 elsif($Hname2=~/\Q$Dirname2\E/i
6329 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006330 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006331 return 1;
6332 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006333 elsif($Hname1=~/(config|lib|util)/i
6334 and $Hname2!~/(config|lib|util)/i)
6335 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006336 return -1;
6337 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006338 elsif($Hname2=~/(config|lib|util)/i
6339 and $Hname1!~/(config|lib|util)/i)
6340 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006341 return 1;
6342 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006343 else
6344 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006345 my $R1 = checkRelevance($H1);
6346 my $R2 = checkRelevance($H2);
6347 if($R1 and not $R2)
6348 { # libebook/e-book.h
6349 return -1;
6350 }
6351 elsif($R2 and not $R1)
6352 { # libebook/e-book.h
6353 return 1;
6354 }
6355 else
6356 {
6357 return (lc($H1) cmp lc($H2));
6358 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006359 }
6360}
6361
6362sub searchForHeaders($)
6363{
6364 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006365
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006366 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006367 registerGccHeaders();
6368
6369 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6370 { # c++ standard include paths
6371 registerCppHeaders();
6372 }
6373
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006374 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006375 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6376 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006377 {
6378 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006379 if($SystemRoot)
6380 {
6381 if(is_abs($Path)) {
6382 $Path = $SystemRoot.$Path;
6383 }
6384 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006385 if(not -e $Path) {
6386 exitStatus("Access_Error", "can't access \'$Path\'");
6387 }
6388 elsif(-f $Path) {
6389 exitStatus("Access_Error", "\'$Path\' - not a directory");
6390 }
6391 elsif(-d $Path)
6392 {
6393 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006394 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006395 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6396 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006397 }
6398 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006399 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006400 }
6401 }
6402 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006403 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006404 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6405 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006406
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006407 # registering directories
6408 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6409 {
6410 next if(not -e $Path);
6411 $Path = get_abs_path($Path);
6412 $Path = path_format($Path, $OSgroup);
6413 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006414 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006415 }
6416 elsif(-f $Path)
6417 {
6418 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006419 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006420 and not $LocalIncludes{$Dir})
6421 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006422 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006423 # if(my $OutDir = get_dirname($Dir))
6424 # { # registering the outer directory
6425 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6426 # and not $LocalIncludes{$OutDir}) {
6427 # registerDir($OutDir, 0, $LibVersion);
6428 # }
6429 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006430 }
6431 }
6432 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006433
6434 # clean memory
6435 %RegisteredDirs = ();
6436
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006437 # registering headers
6438 my $Position = 0;
6439 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6440 {
6441 if(is_abs($Dest) and not -e $Dest) {
6442 exitStatus("Access_Error", "can't access \'$Dest\'");
6443 }
6444 $Dest = path_format($Dest, $OSgroup);
6445 if(is_header($Dest, 1, $LibVersion))
6446 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006447 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006448 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6449 }
6450 }
6451 elsif(-d $Dest)
6452 {
6453 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006454 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006455 {
6456 next if(ignore_path($Path));
6457 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006458 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006459 push(@Registered, $HPath);
6460 }
6461 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006462 @Registered = sort {sortHeaders($a, $b)} @Registered;
6463 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006464 foreach my $Path (@Registered) {
6465 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6466 }
6467 }
6468 else {
6469 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6470 }
6471 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006472
6473 if(defined $Tolerance and $Tolerance=~/4/)
6474 { # 4 - skip headers included by others
6475 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6476 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006477 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006478 delete($Registered_Headers{$LibVersion}{$Path});
6479 }
6480 }
6481 }
6482
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006483 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6484 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006485 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006486 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006487 if(is_abs($Header) and not -f $Header) {
6488 exitStatus("Access_Error", "can't access file \'$Header\'");
6489 }
6490 $Header = path_format($Header, $OSgroup);
6491 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6492 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006493 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006494 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006495 }
6496 else {
6497 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6498 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006499 }
6500 }
6501 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6502 { # set relative paths (for duplicates)
6503 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6504 { # search for duplicates
6505 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6506 my $Prefix = get_dirname($FirstPath);
6507 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6508 { # detect a shortest distinguishing prefix
6509 my $NewPrefix = $1;
6510 my %Identity = ();
6511 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6512 {
6513 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6514 $Identity{$Path} = $1;
6515 }
6516 }
6517 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006518 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006519 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6520 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6521 }
6522 last;
6523 }
6524 $Prefix = $NewPrefix; # increase prefix
6525 }
6526 }
6527 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006528
6529 # clean memory
6530 %HeaderName_Paths = ();
6531
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006532 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6533 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006534 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006535 my ($Pos, $PairPos) = (-1, -1);
6536 my ($Path, $PairPath) = ();
6537 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6538 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6539 foreach my $Header_Path (@Paths)
6540 {
6541 if(get_filename($Header_Path) eq $PairName)
6542 {
6543 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6544 $PairPath = $Header_Path;
6545 }
6546 if(get_filename($Header_Path) eq $HeaderName)
6547 {
6548 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6549 $Path = $Header_Path;
6550 }
6551 }
6552 if($PairPos!=-1 and $Pos!=-1
6553 and int($PairPos)<int($Pos))
6554 {
6555 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6556 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6557 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6558 }
6559 }
6560 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6561 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6562 }
6563}
6564
6565sub detect_real_includes($$)
6566{
6567 my ($AbsPath, $LibVersion) = @_;
6568 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6569 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6570 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6571 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6572 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006573 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6574
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006575 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6576 return () if(not $Path);
6577 open(PREPROC, $Path);
6578 while(<PREPROC>)
6579 {
6580 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6581 {
6582 my $Include = path_format($1, $OSgroup);
6583 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6584 next;
6585 }
6586 if($Include eq $AbsPath) {
6587 next;
6588 }
6589 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6590 }
6591 }
6592 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006593 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6594}
6595
6596sub detect_header_includes($$)
6597{
6598 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006599 return if(not $LibVersion or not $Path);
6600 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6601 return;
6602 }
6603 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6604
6605 if(not -e $Path) {
6606 return;
6607 }
6608
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006609 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006610 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6611 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006612 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006613 {
6614 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006615 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006616 }
6617 if($RedirectPath ne $Path) {
6618 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6619 }
6620 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006621 else
6622 { # can't find
6623 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6624 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006625 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006626 if(my $Inc = parse_includes($Content, $Path))
6627 {
6628 foreach my $Include (keys(%{$Inc}))
6629 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006630 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006631
6632 if(defined $Tolerance and $Tolerance=~/4/)
6633 {
6634 if(my $HPath = identifyHeader($Include, $LibVersion))
6635 {
6636 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6637 }
6638 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006639 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006640 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006641}
6642
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006643sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006644{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006645 my $Path = $_[0];
6646 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006647 if($OStarget eq "symbian")
6648 {
6649 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6650 { # epoc32/include/libc/{stdio, ...}.h
6651 return 1;
6652 }
6653 }
6654 else
6655 {
6656 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6657 { # /usr/include/{stdio, ...}.h
6658 return 1;
6659 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006660 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006661 return 0;
6662}
6663
6664sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006665{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006666 my $Dir = $_[0];
6667 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006668 if($OStarget eq "symbian")
6669 {
6670 if(get_filename($OutDir) eq "libc"
6671 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6672 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6673 return 1;
6674 }
6675 }
6676 else
6677 { # linux
6678 if($OutDir eq "/usr/include"
6679 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6680 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6681 return 1;
6682 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006683 }
6684 return 0;
6685}
6686
6687sub detect_recursive_includes($$)
6688{
6689 my ($AbsPath, $LibVersion) = @_;
6690 return () if(not $AbsPath);
6691 if(isCyclical(\@RecurInclude, $AbsPath)) {
6692 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6693 }
6694 my ($AbsDir, $Name) = separate_path($AbsPath);
6695 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006696 { # system GLIBC internals
6697 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006698 }
6699 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6700 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6701 }
6702 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006703
6704 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6705 { # skip /usr/include/c++/*/ headers
6706 return () if(not $ExtraInfo);
6707 }
6708
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006709 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006710 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006711 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006712 { # check "real" (non-"model") include paths
6713 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6714 pop(@RecurInclude);
6715 return @Paths;
6716 }
6717 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6718 detect_header_includes($AbsPath, $LibVersion);
6719 }
6720 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6721 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006722 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006723 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006724 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006725 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006726 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006727 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006728 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006729 }
6730 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006731 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006732 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006733 { # search for the nearest header
6734 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006735 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006736 if(-f $Candidate) {
6737 $HPath = $Candidate;
6738 }
6739 }
6740 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006741 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006742 }
6743 next if(not $HPath);
6744 if($HPath eq $AbsPath) {
6745 next;
6746 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006747
6748 if($Debug)
6749 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006750# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6751# {
6752# print STDERR "$AbsPath -> $HPath\n";
6753# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006754 }
6755
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006756 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6757 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006758 { # only include <...>, skip include "..." prefixes
6759 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6760 }
6761 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6762 {
6763 if($IncPath eq $AbsPath) {
6764 next;
6765 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006766 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6767 if($RIncType==-1)
6768 { # include "..."
6769 $RIncType = $IncType;
6770 }
6771 elsif($RIncType==2)
6772 {
6773 if($IncType!=-1) {
6774 $RIncType = $IncType;
6775 }
6776 }
6777 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006778 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6779 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6780 }
6781 }
6782 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6783 {
6784 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6785 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6786 { # distinguish math.h from glibc and math.h from the tested library
6787 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6788 last;
6789 }
6790 }
6791 }
6792 pop(@RecurInclude);
6793 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6794}
6795
6796sub find_in_framework($$$)
6797{
6798 my ($Header, $Framework, $LibVersion) = @_;
6799 return "" if(not $Header or not $Framework or not $LibVersion);
6800 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6801 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6802 }
6803 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6804 {
6805 if(get_filename($Dependency) eq $Framework
6806 and -f get_dirname($Dependency)."/".$Header) {
6807 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6808 }
6809 }
6810 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6811}
6812
6813sub find_in_defaults($)
6814{
6815 my $Header = $_[0];
6816 return "" if(not $Header);
6817 if(defined $Cache{"find_in_defaults"}{$Header}) {
6818 return $Cache{"find_in_defaults"}{$Header};
6819 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006820 foreach my $Dir (@DefaultIncPaths,
6821 @DefaultGccPaths,
6822 @DefaultCppPaths,
6823 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006824 {
6825 next if(not $Dir);
6826 if(-f $Dir."/".$Header) {
6827 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6828 }
6829 }
6830 return ($Cache{"find_in_defaults"}{$Header}="");
6831}
6832
6833sub cmp_paths($$)
6834{
6835 my ($Path1, $Path2) = @_;
6836 my @Parts1 = split(/[\/\\]/, $Path1);
6837 my @Parts2 = split(/[\/\\]/, $Path2);
6838 foreach my $Num (0 .. $#Parts1)
6839 {
6840 my $Part1 = $Parts1[$Num];
6841 my $Part2 = $Parts2[$Num];
6842 if($GlibcDir{$Part1}
6843 and not $GlibcDir{$Part2}) {
6844 return 1;
6845 }
6846 elsif($GlibcDir{$Part2}
6847 and not $GlibcDir{$Part1}) {
6848 return -1;
6849 }
6850 elsif($Part1=~/glib/
6851 and $Part2!~/glib/) {
6852 return 1;
6853 }
6854 elsif($Part1!~/glib/
6855 and $Part2=~/glib/) {
6856 return -1;
6857 }
6858 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6859 return $CmpRes;
6860 }
6861 }
6862 return 0;
6863}
6864
6865sub checkRelevance($)
6866{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006867 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006868 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006869
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006870 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006871 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006872 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006873
6874 my $Name = lc(get_filename($Path));
6875 my $Dir = lc(get_dirname($Path));
6876
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006877 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006878
6879 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006880 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006881 my $Len = length($Token);
6882 next if($Len<=1);
6883 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6884 { # include/evolution-data-server-1.4/libebook/e-book.h
6885 return 1;
6886 }
6887 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006888 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006889 return 1;
6890 }
6891 }
6892 return 0;
6893}
6894
6895sub checkFamily(@)
6896{
6897 my @Paths = @_;
6898 return 1 if($#Paths<=0);
6899 my %Prefix = ();
6900 foreach my $Path (@Paths)
6901 {
6902 if($SystemRoot) {
6903 $Path = cut_path_prefix($Path, $SystemRoot);
6904 }
6905 if(my $Dir = get_dirname($Path))
6906 {
6907 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6908 $Prefix{$Dir} += 1;
6909 $Prefix{get_dirname($Dir)} += 1;
6910 }
6911 }
6912 foreach (sort keys(%Prefix))
6913 {
6914 if(get_depth($_)>=3
6915 and $Prefix{$_}==$#Paths+1) {
6916 return 1;
6917 }
6918 }
6919 return 0;
6920}
6921
6922sub isAcceptable($$$)
6923{
6924 my ($Header, $Candidate, $LibVersion) = @_;
6925 my $HName = get_filename($Header);
6926 if(get_dirname($Header))
6927 { # with prefix
6928 return 1;
6929 }
6930 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6931 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6932 return 1;
6933 }
6934 if(checkRelevance($Candidate))
6935 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6936 return 1;
6937 }
6938 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6939 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6940 # /usr/include/qt4/Qt/qsslconfiguration.h
6941 return 1;
6942 }
6943 if($OStarget eq "symbian")
6944 {
6945 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6946 return 1;
6947 }
6948 }
6949 return 0;
6950}
6951
6952sub isRelevant($$$)
6953{ # disallow to search for "abstract" headers in too deep directories
6954 my ($Header, $Candidate, $LibVersion) = @_;
6955 my $HName = get_filename($Header);
6956 if($OStarget eq "symbian")
6957 {
6958 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
6959 return 0;
6960 }
6961 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006962 if($OStarget ne "bsd")
6963 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006964 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
6965 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
6966 return 0;
6967 }
6968 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006969 if($OStarget ne "windows")
6970 {
6971 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
6972 { # skip /usr/include/wine/msvcrt
6973 return 0;
6974 }
6975 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006976 if(not get_dirname($Header)
6977 and $Candidate=~/[\/\\]wx[\/\\]/)
6978 { # do NOT search in system /wx/ directory
6979 # for headers without a prefix: sstream.h
6980 return 0;
6981 }
6982 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
6983 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
6984 { # skip ../c++/3.3.3/ if using ../c++/4.5/
6985 return 0;
6986 }
6987 if($Candidate=~/[\/\\]asm-/
6988 and (my $Arch = getArch($LibVersion)) ne "unknown")
6989 { # arch-specific header files
6990 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
6991 {# skip ../asm-arm/ if using x86 architecture
6992 return 0;
6993 }
6994 }
6995 my @Candidates = getSystemHeaders($HName, $LibVersion);
6996 if($#Candidates==1)
6997 { # unique header
6998 return 1;
6999 }
7000 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7001 if($#SCandidates==1)
7002 { # unique name
7003 return 1;
7004 }
7005 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7006 if(get_depth($Candidate)-$SystemDepth>=5)
7007 { # abstract headers in too deep directories
7008 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7009 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7010 return 0;
7011 }
7012 }
7013 if($Header eq "parser.h"
7014 and $Candidate!~/\/libxml2\//)
7015 { # select parser.h from xml2 library
7016 return 0;
7017 }
7018 if(not get_dirname($Header)
7019 and keys(%{$SystemHeaders{$HName}})>=3)
7020 { # many headers with the same name
7021 # like thread.h included without a prefix
7022 if(not checkFamily(@Candidates)) {
7023 return 0;
7024 }
7025 }
7026 return 1;
7027}
7028
7029sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007030{ # cache function
7031 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7032 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7033 }
7034 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7035}
7036
7037sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007038{
7039 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007040 if(-f $Header) {
7041 return $Header;
7042 }
7043 if(is_abs($Header) and not -f $Header)
7044 { # incorrect absolute path
7045 return "";
7046 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007047 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007048 { # too abstract configuration headers
7049 return "";
7050 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007051 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007052 if($OSgroup ne "windows")
7053 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007054 if(defined $WinHeaders{lc($HName)}
7055 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007056 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007057 return "";
7058 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007059 }
7060 if($OSgroup ne "macos")
7061 {
7062 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007063 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007064 return "";
7065 }
7066 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007067
7068 if(defined $ObsoleteHeaders{$HName})
7069 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007070 return "";
7071 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007072 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7073 {
7074 if(defined $AlienHeaders{$HName}
7075 or defined $AlienHeaders{$Header})
7076 { # alien headers from other systems
7077 return "";
7078 }
7079 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007080
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007081 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007082 { # search in default paths
7083 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007084 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007085 }
7086 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007087 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007088 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007089 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007090 }
7091 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7092 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7093 {
7094 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007095 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007096 }
7097 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007098 # error
7099 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007100}
7101
7102sub getSystemHeaders($$)
7103{
7104 my ($Header, $LibVersion) = @_;
7105 my @Candidates = ();
7106 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7107 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007108 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007109 next;
7110 }
7111 push(@Candidates, $Candidate);
7112 }
7113 return @Candidates;
7114}
7115
7116sub cut_path_prefix($$)
7117{
7118 my ($Path, $Prefix) = @_;
7119 return $Path if(not $Prefix);
7120 $Prefix=~s/[\/\\]+\Z//;
7121 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7122 return $Path;
7123}
7124
7125sub is_default_include_dir($)
7126{
7127 my $Dir = $_[0];
7128 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007129 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007130}
7131
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007132sub identifyHeader($$)
7133{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007134 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007135 if(not $Header) {
7136 return "";
7137 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007138 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007139 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7140 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007141 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007142 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007143}
7144
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007145sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007146{ # search for header by absolute path, relative path or name
7147 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007148 if(-f $Header)
7149 { # it's relative or absolute path
7150 return get_abs_path($Header);
7151 }
7152 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7153 and my $HeaderDir = find_in_defaults($Header))
7154 { # search for libc headers in the /usr/include
7155 # for non-libc target library before searching
7156 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007157 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007158 }
7159 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7160 { # search in the target library paths
7161 return $Path;
7162 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007163 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007164 { # search in the internal GCC include paths
7165 return $DefaultGccHeader{$Header};
7166 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007167 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007168 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007169 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007170 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007171 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007172 { # search in the default G++ include paths
7173 return $DefaultCppHeader{$Header};
7174 }
7175 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7176 { # search everywhere in the system
7177 return $AnyPath;
7178 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007179 elsif($OSgroup eq "macos")
7180 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7181 if(my $Dir = get_dirname($Header))
7182 {
7183 my $RelPath = "Headers\/".get_filename($Header);
7184 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007185 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007186 }
7187 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007188 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007189 # cannot find anything
7190 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007191}
7192
7193sub getLocation($)
7194{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007195 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7196 {
7197 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007198 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007199 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007200 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007201 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007202}
7203
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007204sub getNameByInfo($)
7205{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007206 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007207 {
7208 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7209 {
7210 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7211 {
7212 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7213 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007214 my $Str = $1;
7215 if($CppMode{$Version}
7216 and $Str=~/\Ac99_(.+)\Z/)
7217 {
7218 if($CppKeywords_A{$1}) {
7219 $Str=$1;
7220 }
7221 }
7222 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007223 }
7224 }
7225 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007226 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007227 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007228}
7229
7230sub getTreeStr($)
7231{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007232 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007233 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007234 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7235 {
7236 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007237 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007238 and $Str=~/\Ac99_(.+)\Z/)
7239 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007240 if($CppKeywords_A{$1}) {
7241 $Str=$1;
7242 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007243 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007244 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007245 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007246 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007247 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007248}
7249
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007250sub getFuncShortName($)
7251{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007252 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007253 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007254 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007255 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007256 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007257 {
7258 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7259 {
7260 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7261 return "operator ".$RName;
7262 }
7263 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007264 }
7265 else
7266 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007267 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7268 {
7269 if(my $Ind = $Operator_Indication{$1}) {
7270 return "operator".$Ind;
7271 }
7272 elsif(not $UnknownOperator{$1})
7273 {
7274 printMsg("WARNING", "unknown operator $1");
7275 $UnknownOperator{$1} = 1;
7276 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007277 }
7278 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007279 }
7280 else
7281 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007282 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7283 return getTreeStr($1);
7284 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007285 }
7286 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007287 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007288}
7289
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007290sub getFuncReturn($)
7291{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007292 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7293 {
7294 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7295 {
7296 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7297 return $1;
7298 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007299 }
7300 }
7301 return "";
7302}
7303
7304sub getFuncOrig($)
7305{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007306 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7307 {
7308 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7309 return $1;
7310 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007311 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007312 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007313}
7314
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007315sub unmangleArray(@)
7316{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007317 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007318 { # MSVC mangling
7319 my $UndNameCmd = get_CmdPath("undname");
7320 if(not $UndNameCmd) {
7321 exitStatus("Not_Found", "can't find \"undname\"");
7322 }
7323 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007324 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007325 }
7326 else
7327 { # GCC mangling
7328 my $CppFiltCmd = get_CmdPath("c++filt");
7329 if(not $CppFiltCmd) {
7330 exitStatus("Not_Found", "can't find c++filt in PATH");
7331 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007332 if(not defined $CPPFILT_SUPPORT_FILE)
7333 {
7334 my $Info = `$CppFiltCmd -h 2>&1`;
7335 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7336 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007337 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007338 if($CPPFILT_SUPPORT_FILE)
7339 { # new versions of c++filt can take a file
7340 if($#_>$MAX_CPPFILT_FILE_SIZE)
7341 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7342 # this is fixed in the oncoming version of Binutils
7343 my @Half = splice(@_, 0, ($#_+1)/2);
7344 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007345 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007346 else
7347 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007348 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7349 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7350 if($?==139)
7351 { # segmentation fault
7352 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7353 }
7354 return split(/\n/, $Res);
7355 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007356 }
7357 else
7358 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007359 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7360 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007361 my @Half = splice(@_, 0, ($#_+1)/2);
7362 return (unmangleArray(@Half), unmangleArray(@_))
7363 }
7364 else
7365 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007366 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007367 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7368 if($?==139)
7369 { # segmentation fault
7370 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7371 }
7372 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007373 }
7374 }
7375 }
7376}
7377
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007378sub get_ChargeLevel($$)
7379{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007380 my ($Symbol, $LibVersion) = @_;
7381 return "" if($Symbol!~/\A(_Z|\?)/);
7382 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7383 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007384 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007385 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007386 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007387 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007388 return "[in-charge]";
7389 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007390 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007391 return "[not-in-charge]";
7392 }
7393 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007394 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007395 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007396 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007397 return "[in-charge]";
7398 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007399 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007400 return "[not-in-charge]";
7401 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007402 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007403 return "[in-charge-deleting]";
7404 }
7405 }
7406 }
7407 else
7408 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007409 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007410 return "[in-charge]";
7411 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007412 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007413 return "[not-in-charge]";
7414 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007415 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007416 return "[in-charge]";
7417 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007418 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007419 return "[not-in-charge]";
7420 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007421 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007422 return "[in-charge-deleting]";
7423 }
7424 }
7425 return "";
7426}
7427
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007428sub get_Signature_M($$)
7429{
7430 my ($Symbol, $LibVersion) = @_;
7431 my $Signature_M = $tr_name{$Symbol};
7432 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7433 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007434 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007435 }
7436 return $Signature_M;
7437}
7438
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007439sub get_Signature($$)
7440{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007441 my ($Symbol, $LibVersion) = @_;
7442 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7443 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007444 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007445 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007446 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03007447
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007448 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7449 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007450 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007451 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7452 {
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007453 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
7454 $ClassName=~s/\bstruct //g;
7455 $Signature .= $ClassName."::";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007456 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7457 $Signature .= "~";
7458 }
7459 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007460 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007461 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007462 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007463 }
7464 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007465 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007466 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007467 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7468 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007469 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007470 else
7471 {
7472 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007473 }
7474 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007475 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007476 {
7477 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007478 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007479 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007480 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007481 if(not $ParamTypeName) {
7482 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7483 }
7484 foreach my $Typedef (keys(%ChangedTypedef))
7485 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007486 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7487 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7488 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007489 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007490 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7491 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007492 if($ParamName eq "this"
7493 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007494 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007495 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007496 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007497 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007498 }
7499 else {
7500 push(@ParamArray, $ParamTypeName);
7501 }
7502 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007503 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7504 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007505 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007506 }
7507 else
7508 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007509 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007510 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007511 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007512 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007513 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007514 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7515 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007516 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007517 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007518 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7519 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007520 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007521 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007522 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7523 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007524 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007525 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007526 }
7527 }
7528 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007529 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007530 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007531 }
7532 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007533 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007534 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007535 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007536}
7537
7538sub create_member_decl($$)
7539{
7540 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007541 if($TName=~/\([\*]+\)/)
7542 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007543 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7544 return $TName;
7545 }
7546 else
7547 {
7548 my @ArraySizes = ();
7549 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7550 push(@ArraySizes, $1);
7551 }
7552 return $TName." ".$Member.join("", @ArraySizes);
7553 }
7554}
7555
7556sub getFuncType($)
7557{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007558 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7559 {
7560 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7561 {
7562 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7563 {
7564 if($Type eq "method_type") {
7565 return "Method";
7566 }
7567 elsif($Type eq "function_type") {
7568 return "Function";
7569 }
7570 else {
7571 return "Other";
7572 }
7573 }
7574 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007575 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007576 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007577}
7578
7579sub getFuncTypeId($)
7580{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007581 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7582 {
7583 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7584 return $1;
7585 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007586 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007587 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007588}
7589
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007590sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007591{ # "._N" or "$_N" in older GCC versions
7592 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007593}
7594
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007595sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007596{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007597 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7598 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007599 }
7600
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007601 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007602
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007603 if($_[1] ne "S")
7604 {
7605 $N=~s/\A[ ]+//g;
7606 $N=~s/[ ]+\Z//g;
7607 $N=~s/[ ]{2,}/ /g;
7608 }
7609
7610 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007611
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007612 $N=~s/\b(const|volatile) ([\w\:]+)([\*&,>]|\Z)/$2 $1$3/g; # "const void" to "void const"
7613
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007614 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007615
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007616 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7617 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007618
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007619 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007620
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007621 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007622
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007623 if($_[1] eq "S")
7624 {
7625 if(index($N, "operator")!=-1) {
7626 $N=~s/\b(operator[ ]*)> >/$1>>/;
7627 }
7628 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007629
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007630 $N=~s/,/, /g;
7631
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007632 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007633}
7634
7635sub get_HeaderDeps($$)
7636{
7637 my ($AbsPath, $LibVersion) = @_;
7638 return () if(not $AbsPath or not $LibVersion);
7639 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7640 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7641 }
7642 my %IncDir = ();
7643 detect_recursive_includes($AbsPath, $LibVersion);
7644 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7645 {
7646 next if(not $HeaderPath);
7647 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7648 my $Dir = get_dirname($HeaderPath);
7649 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7650 {
7651 my $Dep = $Dir;
7652 if($Prefix)
7653 {
7654 if($OSgroup eq "windows")
7655 { # case insensitive seach on windows
7656 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7657 next;
7658 }
7659 }
7660 elsif($OSgroup eq "macos")
7661 { # seach in frameworks
7662 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7663 {
7664 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7665 {# frameworks
7666 my ($HFramework, $HName) = ($1, $2);
7667 $Dep = $HFramework;
7668 }
7669 else
7670 {# mismatch
7671 next;
7672 }
7673 }
7674 }
7675 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7676 { # Linux, FreeBSD
7677 next;
7678 }
7679 }
7680 if(not $Dep)
7681 { # nothing to include
7682 next;
7683 }
7684 if(is_default_include_dir($Dep))
7685 { # included by the compiler
7686 next;
7687 }
7688 if(get_depth($Dep)==1)
7689 { # too short
7690 next;
7691 }
7692 if(isLibcDir($Dep))
7693 { # do NOT include /usr/include/{sys,bits}
7694 next;
7695 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007696 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007697 }
7698 }
7699 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7700 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7701}
7702
7703sub sortIncPaths($$)
7704{
7705 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007706 if(not $ArrRef or $#{$ArrRef}<0) {
7707 return $ArrRef;
7708 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007709 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7710 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007711 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007712 return $ArrRef;
7713}
7714
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007715sub sortDeps($$$)
7716{
7717 if($Header_Dependency{$_[2]}{$_[0]}
7718 and not $Header_Dependency{$_[2]}{$_[1]}) {
7719 return 1;
7720 }
7721 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7722 and $Header_Dependency{$_[2]}{$_[1]}) {
7723 return -1;
7724 }
7725 return 0;
7726}
7727
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007728sub join_P($$)
7729{
7730 my $S = "/";
7731 if($OSgroup eq "windows") {
7732 $S = "\\";
7733 }
7734 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007735}
7736
7737sub get_namespace_additions($)
7738{
7739 my $NameSpaces = $_[0];
7740 my ($Additions, $AddNameSpaceId) = ("", 1);
7741 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7742 {
7743 next if($SkipNameSpaces{$Version}{$NS});
7744 next if(not $NS or $NameSpaces->{$NS}==-1);
7745 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7746 next if($NS=~/\A__/i);
7747 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007748 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007749 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7750 my @NS_Parts = split(/::/, $NS);
7751 next if($#NS_Parts==-1);
7752 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7753 foreach my $NS_Part (@NS_Parts)
7754 {
7755 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7756 $TypeDecl_Suffix .= "}";
7757 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007758 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007759 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7760 $Additions.=" $TypeDecl\n $FuncDecl\n";
7761 $AddNameSpaceId+=1;
7762 }
7763 return $Additions;
7764}
7765
7766sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007767{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007768 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007769 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007770 if($Fmt eq "windows")
7771 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007772 $Path=~s/\//\\/g;
7773 $Path=lc($Path);
7774 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007775 else
7776 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007777 $Path=~s/\\/\//g;
7778 }
7779 return $Path;
7780}
7781
7782sub inc_opt($$)
7783{
7784 my ($Path, $Style) = @_;
7785 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007786 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007787 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007788 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007789 return "-I\"".path_format($Path, "unix")."\"";
7790 }
7791 elsif($OSgroup eq "macos"
7792 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007793 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007794 return "-F".esc(get_dirname($Path));
7795 }
7796 else {
7797 return "-I".esc($Path);
7798 }
7799 }
7800 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007801 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007802 }
7803 return "";
7804}
7805
7806sub platformSpecs($)
7807{
7808 my $LibVersion = $_[0];
7809 my $Arch = getArch($LibVersion);
7810 if($OStarget eq "symbian")
7811 { # options for GCCE compiler
7812 my %Symbian_Opts = map {$_=>1} (
7813 "-D__GCCE__",
7814 "-DUNICODE",
7815 "-fexceptions",
7816 "-D__SYMBIAN32__",
7817 "-D__MARM_INTERWORK__",
7818 "-D_UNICODE",
7819 "-D__S60_50__",
7820 "-D__S60_3X__",
7821 "-D__SERIES60_3X__",
7822 "-D__EPOC32__",
7823 "-D__MARM__",
7824 "-D__EABI__",
7825 "-D__MARM_ARMV5__",
7826 "-D__SUPPORT_CPP_EXCEPTIONS__",
7827 "-march=armv5t",
7828 "-mapcs",
7829 "-mthumb-interwork",
7830 "-DEKA2",
7831 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7832 );
7833 return join(" ", keys(%Symbian_Opts));
7834 }
7835 elsif($OSgroup eq "windows"
7836 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7837 { # add options to MinGW compiler
7838 # to simulate the MSVC compiler
7839 my %MinGW_Opts = map {$_=>1} (
7840 "-D_WIN32",
7841 "-D_STDCALL_SUPPORTED",
7842 "-D__int64=\"long long\"",
7843 "-D__int32=int",
7844 "-D__int16=short",
7845 "-D__int8=char",
7846 "-D__possibly_notnullterminated=\" \"",
7847 "-D__nullterminated=\" \"",
7848 "-D__nullnullterminated=\" \"",
7849 "-D__w64=\" \"",
7850 "-D__ptr32=\" \"",
7851 "-D__ptr64=\" \"",
7852 "-D__forceinline=inline",
7853 "-D__inline=inline",
7854 "-D__uuidof(x)=IID()",
7855 "-D__try=",
7856 "-D__except(x)=",
7857 "-D__declspec(x)=__attribute__((x))",
7858 "-D__pragma(x)=",
7859 "-D_inline=inline",
7860 "-D__forceinline=__inline",
7861 "-D__stdcall=__attribute__((__stdcall__))",
7862 "-D__cdecl=__attribute__((__cdecl__))",
7863 "-D__fastcall=__attribute__((__fastcall__))",
7864 "-D__thiscall=__attribute__((__thiscall__))",
7865 "-D_stdcall=__attribute__((__stdcall__))",
7866 "-D_cdecl=__attribute__((__cdecl__))",
7867 "-D_fastcall=__attribute__((__fastcall__))",
7868 "-D_thiscall=__attribute__((__thiscall__))",
7869 "-DSHSTDAPI_(x)=x",
7870 "-D_MSC_EXTENSIONS",
7871 "-DSECURITY_WIN32",
7872 "-D_MSC_VER=1500",
7873 "-D_USE_DECLSPECS_FOR_SAL",
7874 "-D__noop=\" \"",
7875 "-DDECLSPEC_DEPRECATED=\" \"",
7876 "-D__builtin_alignof(x)=__alignof__(x)",
7877 "-DSORTPP_PASS");
7878 if($Arch eq "x86") {
7879 $MinGW_Opts{"-D_M_IX86=300"}=1;
7880 }
7881 elsif($Arch eq "x86_64") {
7882 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7883 }
7884 elsif($Arch eq "ia64") {
7885 $MinGW_Opts{"-D_M_IA64=300"}=1;
7886 }
7887 return join(" ", keys(%MinGW_Opts));
7888 }
7889 return "";
7890}
7891
7892my %C_Structure = map {$_=>1} (
7893# FIXME: Can't separate union and struct data types before dumping,
7894# so it sometimes cause compilation errors for unknown reason
7895# when trying to declare TYPE* tmp_add_class_N
7896# This is a list of such structures + list of other C structures
7897 "sigval",
7898 "sigevent",
7899 "sigaction",
7900 "sigvec",
7901 "sigstack",
7902 "timeval",
7903 "timezone",
7904 "rusage",
7905 "rlimit",
7906 "wait",
7907 "flock",
7908 "stat",
7909 "_stat",
7910 "stat32",
7911 "_stat32",
7912 "stat64",
7913 "_stat64",
7914 "_stati64",
7915 "if_nameindex",
7916 "usb_device",
7917 "sigaltstack",
7918 "sysinfo",
7919 "timeLocale",
7920 "tcp_debug",
7921 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007922 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007923 "timespec",
7924 "random_data",
7925 "drand48_data",
7926 "_IO_marker",
7927 "_IO_FILE",
7928 "lconv",
7929 "sched_param",
7930 "tm",
7931 "itimerspec",
7932 "_pthread_cleanup_buffer",
7933 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007934 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007935 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007936 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007937 "sigcontext",
7938 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007939 # Mac
7940 "_timex",
7941 "_class_t",
7942 "_category_t",
7943 "_class_ro_t",
7944 "_protocol_t",
7945 "_message_ref_t",
7946 "_super_message_ref_t",
7947 "_ivar_t",
7948 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007949);
7950
7951sub getCompileCmd($$$)
7952{
7953 my ($Path, $Opt, $Inc) = @_;
7954 my $GccCall = $GCC_PATH;
7955 if($Opt) {
7956 $GccCall .= " ".$Opt;
7957 }
7958 $GccCall .= " -x ";
7959 if($OSgroup eq "macos") {
7960 $GccCall .= "objective-";
7961 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007962
7963 if($EMERGENCY_MODE_48)
7964 { # workaround for GCC 4.8 (C only)
7965 $GccCall .= "c++";
7966 }
7967 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007968 { # compile as "C++" header
7969 # to obtain complete dump using GCC 4.0
7970 $GccCall .= "c++-header";
7971 }
7972 else
7973 { # compile as "C++" source
7974 # GCC 3.3 cannot compile headers
7975 $GccCall .= "c++";
7976 }
7977 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007978 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007979 $GccCall .= " ".$Opts;
7980 }
7981 # allow extra qualifications
7982 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007983 $GccCall .= " -fpermissive";
7984 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007985 if($NoStdInc)
7986 {
7987 $GccCall .= " -nostdinc";
7988 $GccCall .= " -nostdinc++";
7989 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007990 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007991 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007992 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007993 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007994 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007995 if($Inc)
7996 { # include paths
7997 $GccCall .= " ".$Inc;
7998 }
7999 return $GccCall;
8000}
8001
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008002sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008003{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008004 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008005 my %HeaderElems = (
8006 # Types
8007 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008008 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008009 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8010 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008011 "time.h" => ["time_t"],
8012 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008013 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8014 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008015 "stdbool.h" => ["_Bool"],
8016 "rpc/xdr.h" => ["bool_t"],
8017 "in_systm.h" => ["n_long", "n_short"],
8018 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008019 "arpa/inet.h" => ["fw_src", "ip_src"],
8020 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008021 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008022 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008023 );
8024 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008025 foreach (keys(%HeaderElems))
8026 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008027 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008028 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008029 }
8030 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008031 my %Types = ();
8032 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8033 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008034 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008035 }
8036 if(keys(%Types))
8037 {
8038 my %AddHeaders = ();
8039 foreach my $Type (keys(%Types))
8040 {
8041 if(my $Header = $AutoPreamble{$Type})
8042 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008043 if(my $Path = identifyHeader($Header, $LibVersion))
8044 {
8045 if(skipHeader($Path, $LibVersion)) {
8046 next;
8047 }
8048 $Path = path_format($Path, $OSgroup);
8049 $AddHeaders{$Path}{"Type"} = $Type;
8050 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008051 }
8052 }
8053 }
8054 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008055 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008056 }
8057 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008058 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008059}
8060
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008061sub checkCTags($)
8062{
8063 my $Path = $_[0];
8064 if(not $Path) {
8065 return;
8066 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008067 my $CTags = undef;
8068
8069 if($OSgroup eq "bsd")
8070 { # use ectags on BSD
8071 $CTags = get_CmdPath("ectags");
8072 if(not $CTags) {
8073 printMsg("WARNING", "can't find \'ectags\' program");
8074 }
8075 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008076 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008077 $CTags = get_CmdPath("ctags");
8078 }
8079 if(not $CTags)
8080 {
8081 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008082 return;
8083 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008084
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008085 if($OSgroup ne "linux")
8086 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008087 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8088 if($Info!~/exuberant/i)
8089 {
8090 printMsg("WARNING", "incompatible version of \'ctags\' program");
8091 return;
8092 }
8093 }
8094
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008095 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008096 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008097 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008098 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008099 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008100 open(CTAGS, "<", $Out);
8101 while(my $Line = <CTAGS>)
8102 {
8103 chomp($Line);
8104 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008105 if(defined $Intrinsic_Keywords{$Name})
8106 { # noise
8107 next;
8108 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008109 if($Type eq "n")
8110 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008111 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008112 next;
8113 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008114 if(index($Scpe, "struct:")==0) {
8115 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008116 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008117 if(index($Scpe, "namespace:")==0)
8118 {
8119 if($Scpe=~s/\Anamespace://) {
8120 $Name = $Scpe."::".$Name;
8121 }
8122 }
8123 $TUnit_NameSpaces{$Version}{$Name} = 1;
8124 }
8125 elsif($Type eq "p")
8126 {
8127 if(not $Scpe or index($Scpe, "namespace:")==0) {
8128 $TUnit_Funcs{$Version}{$Name} = 1;
8129 }
8130 }
8131 elsif($Type eq "x")
8132 {
8133 if(not $Scpe or index($Scpe, "namespace:")==0) {
8134 $TUnit_Vars{$Version}{$Name} = 1;
8135 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008136 }
8137 }
8138 close(CTAGS);
8139}
8140
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008141sub preChange($$)
8142{
8143 my ($HeaderPath, $IncStr) = @_;
8144
8145 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8146 my $Content = undef;
8147
8148 if($OStarget eq "windows"
8149 and get_dumpmachine($GCC_PATH)=~/mingw/i
8150 and $MinGWMode{$Version}!=-1)
8151 { # modify headers to compile by MinGW
8152 if(not $Content)
8153 { # preprocessing
8154 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8155 }
8156 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8157 { # __asm { ... }
8158 $MinGWMode{$Version}=1;
8159 }
8160 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8161 { # comments after preprocessing
8162 $MinGWMode{$Version}=1;
8163 }
8164 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8165 { # 0xffui8
8166 $MinGWMode{$Version}=1;
8167 }
8168
8169 if($MinGWMode{$Version}) {
8170 printMsg("INFO", "Using MinGW compatibility mode");
8171 }
8172 }
8173
8174 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8175 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8176 { # rename C++ keywords in C code
8177 # disable this code by -cpp-compatible option
8178 if(not $Content)
8179 { # preprocessing
8180 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8181 }
8182 my $RegExp_C = join("|", keys(%CppKeywords_C));
8183 my $RegExp_F = join("|", keys(%CppKeywords_F));
8184 my $RegExp_O = join("|", keys(%CppKeywords_O));
8185
8186 my $Detected = undef;
8187
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008188 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 +04008189 { # MATCH:
8190 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008191 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008192 # unsigned private: 8;
8193 # DO NOT MATCH:
8194 # #pragma GCC visibility push(default)
8195 $CppMode{$Version} = 1;
8196 $Detected = "$1$2$3$4" if(not defined $Detected);
8197 }
8198 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8199 { # MATCH:
8200 # int delete(...);
8201 # int explicit(...);
8202 # DO NOT MATCH:
8203 # void operator delete(...)
8204 $CppMode{$Version} = 1;
8205 $Detected = "$1$2$3" if(not defined $Detected);
8206 }
8207 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8208 { # MATCH:
8209 # int bool;
8210 # DO NOT MATCH:
8211 # bool X;
8212 # return *this;
8213 # throw;
8214 $CppMode{$Version} = 1;
8215 $Detected = "$1$2$3" if(not defined $Detected);
8216 }
8217 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8218 { # MATCH:
8219 # int operator(...);
8220 # DO NOT MATCH:
8221 # int operator()(...);
8222 $CppMode{$Version} = 1;
8223 $Detected = "$1$2$3" if(not defined $Detected);
8224 }
8225 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8226 { # MATCH:
8227 # int foo(int operator);
8228 # int foo(int operator, int other);
8229 # DO NOT MATCH:
8230 # int operator,(...);
8231 $CppMode{$Version} = 1;
8232 $Detected = "$1$2$3" if(not defined $Detected);
8233 }
8234 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8235 { # MATCH:
8236 # int foo(gboolean *bool);
8237 # DO NOT MATCH:
8238 # void setTabEnabled(int index, bool);
8239 $CppMode{$Version} = 1;
8240 $Detected = "$1$2$3" if(not defined $Detected);
8241 }
8242 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8243 { # MATCH:
8244 # int foo(int* this);
8245 # int bar(int this);
8246 # int baz(int throw);
8247 # DO NOT MATCH:
8248 # foo(X, this);
8249 $CppMode{$Version} = 1;
8250 $Detected = "$1$2$3$4" if(not defined $Detected);
8251 }
8252 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8253 { # MATCH:
8254 # struct template {...};
8255 # extern template foo(...);
8256 $CppMode{$Version} = 1;
8257 $Detected = "$1$2" if(not defined $Detected);
8258 }
8259
8260 if($CppMode{$Version} == 1)
8261 {
8262 if($Debug)
8263 {
8264 $Detected=~s/\A\s+//g;
8265 printMsg("INFO", "Detected code: \"$Detected\"");
8266 }
8267 }
8268
8269 # remove typedef enum NAME NAME;
8270 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8271 my $N = 0;
8272 while($N<=$#FwdTypedefs-1)
8273 {
8274 my $S = $FwdTypedefs[$N];
8275 if($S eq $FwdTypedefs[$N+1])
8276 {
8277 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008278 $CppMode{$Version} = 1;
8279
8280 if($Debug) {
8281 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8282 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008283 }
8284 $N+=2;
8285 }
8286
8287 if($CppMode{$Version}==1) {
8288 printMsg("INFO", "Using C++ compatibility mode");
8289 }
8290 }
8291
8292 if($CppMode{$Version}==1
8293 or $MinGWMode{$Version}==1)
8294 {
8295 my $IPath = $TMP_DIR."/dump$Version.i";
8296 writeFile($IPath, $Content);
8297 return $IPath;
8298 }
8299
8300 return undef;
8301}
8302
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008303sub getDump()
8304{
8305 if(not $GCC_PATH) {
8306 exitStatus("Error", "internal error - GCC path is not set");
8307 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008308
8309 my @Headers = keys(%{$Registered_Headers{$Version}});
8310 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8311
8312 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8313
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008314 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008315 my $HeaderPath = $TmpHeaderPath;
8316
8317 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008318 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008319 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8320 {
8321 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008322 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008323 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008324 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008325 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8326 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008327 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008328 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008329 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008330 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8331 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8332 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008333 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008334 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008335
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008336 if($ExtraInfo)
8337 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008338 if($IncludeString) {
8339 writeFile($ExtraInfo."/include-string", $IncludeString);
8340 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008341 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8342 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008343
8344 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8345 {
8346 my $REDIR = "";
8347 foreach my $P1 (sort @Redirects) {
8348 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8349 }
8350 writeFile($ExtraInfo."/include-redirect", $REDIR);
8351 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008352 }
8353
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008354 if(not keys(%{$TargetHeaders{$Version}}))
8355 { # Target headers
8356 addTargetHeaders($Version);
8357 }
8358
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008359 # clean memory
8360 %RecursiveIncludes = ();
8361 %Header_Include_Prefix = ();
8362 %Header_Includes = ();
8363
8364 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008365 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008366 delete($Cache{"detect_header_includes"});
8367 delete($Cache{"selectSystemHeader"});
8368
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008369 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008370 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8371 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008372
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008373 if($ExtraInfo)
8374 { # extra information for other tools
8375 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8376 }
8377
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008378 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008379 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008380 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008381
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008382 if($COMMON_LANGUAGE{$Version} eq "C++") {
8383 checkCTags($Pre);
8384 }
8385
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008386 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8387 { # try to correct the preprocessor output
8388 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008389 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008390
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008391 if($COMMON_LANGUAGE{$Version} eq "C++")
8392 { # add classes and namespaces to the dump
8393 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008394 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008395 or $MinGWMode{$Version}==1) {
8396 $CHdump .= " -fpreprocessed";
8397 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008398 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008399 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008400 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008401 chdir($ORIG_DIR);
8402 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8403 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008404 my $Content = readFile($ClassDump);
8405 foreach my $ClassInfo (split(/\n\n/, $Content))
8406 {
8407 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8408 {
8409 my $CName = $1;
8410 next if($CName=~/\A(__|_objc_|_opaque_)/);
8411 $TUnit_NameSpaces{$Version}{$CName} = -1;
8412 if($CName=~/\A[\w:]+\Z/)
8413 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008414 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008415 }
8416 if($CName=~/(\w[\w:]*)::/)
8417 { # namespaces
8418 my $NS = $1;
8419 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8420 $TUnit_NameSpaces{$Version}{$NS} = 1;
8421 }
8422 }
8423 }
8424 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8425 { # read v-tables (advanced approach)
8426 my ($CName, $VTable) = ($1, $2);
8427 $ClassVTable_Content{$Version}{$CName} = $VTable;
8428 }
8429 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008430 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8431 { # add user-defined namespaces
8432 $TUnit_NameSpaces{$Version}{$NS} = 1;
8433 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008434 if($Debug)
8435 { # debug mode
8436 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008437 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008438 }
8439 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008440 }
8441
8442 # add namespaces and classes
8443 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8444 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008445 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008446 }
8447 # some GCC versions don't include class methods to the TU dump by default
8448 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008449 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008450 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8451 {
8452 next if($C_Structure{$CName});
8453 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008454 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008455 if(not $Force and $GCC_44
8456 and $OSgroup eq "linux")
8457 { # optimization for linux with GCC >= 4.4
8458 # disable this code by -force option
8459 if(index($CName, "::")!=-1)
8460 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008461 next;
8462 }
8463 }
8464 else
8465 {
8466 if($CName=~/\A(.+)::[^:]+\Z/
8467 and $TUnit_Classes{$Version}{$1})
8468 { # classes inside other classes
8469 next;
8470 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008471 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008472 if(defined $TUnit_Funcs{$Version}{$CName})
8473 { # the same name for a function and type
8474 next;
8475 }
8476 if(defined $TUnit_Vars{$Version}{$CName})
8477 { # the same name for a variable and type
8478 next;
8479 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008480 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8481 }
8482 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008483 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008484 }
8485 }
8486 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8487 # create TU dump
8488 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008489 if($UserLang eq "C") {
8490 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8491 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008492 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008493 or $MinGWMode{$Version}==1) {
8494 $TUdump .= " -fpreprocessed";
8495 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008496 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008497 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8498 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008499 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008500 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008501 if($?)
8502 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008503 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008504 { # try to recompile
8505 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008506 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008507 and index($Errors, "c99_")!=-1
8508 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008509 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008510 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008511
8512 if($Debug)
8513 {
8514 # printMsg("INFO", $Errors);
8515 }
8516
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008517 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008518 resetLogging($Version);
8519 $TMP_DIR = tempdir(CLEANUP=>1);
8520 return getDump();
8521 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008522 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008523 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008524 { # add auto preamble headers and try again
8525 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008526 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008527 foreach my $Num (0 .. $#Headers)
8528 {
8529 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008530 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8531 {
8532 push_U($Include_Preamble{$Version}, $Path);
8533 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008534 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008535 }
8536 resetLogging($Version);
8537 $TMP_DIR = tempdir(CLEANUP=>1);
8538 return getDump();
8539 }
8540 elsif($Cpp0xMode{$Version}!=-1
8541 and ($Errors=~/\Q-std=c++0x\E/
8542 or $Errors=~/is not a class or namespace/))
8543 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008544 if(check_gcc($GCC_PATH, "4.6"))
8545 {
8546 $Cpp0xMode{$Version}=-1;
8547 printMsg("INFO", "Enabling c++0x mode");
8548 resetLogging($Version);
8549 $TMP_DIR = tempdir(CLEANUP=>1);
8550 $CompilerOptions{$Version} .= " -std=c++0x";
8551 return getDump();
8552 }
8553 else {
8554 printMsg("WARNING", "Probably c++0x construction detected");
8555 }
8556
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008557 }
8558 elsif($MinGWMode{$Version}==1)
8559 { # disable MinGW mode and try again
8560 $MinGWMode{$Version}=-1;
8561 resetLogging($Version);
8562 $TMP_DIR = tempdir(CLEANUP=>1);
8563 return getDump();
8564 }
8565 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008566 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008567 else {
8568 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008569 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008570 printMsg("ERROR", "some errors occurred when compiling headers");
8571 printErrorLog($Version);
8572 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008573 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008574 }
8575 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008576 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008577 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008578
8579 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8580 return $TUs[0];
8581 }
8582 else
8583 {
8584 my $Msg = "can't compile header(s)";
8585 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8586 $Msg .= "\nDid you install G++?";
8587 }
8588 exitStatus("Cannot_Compile", $Msg);
8589 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008590}
8591
8592sub cmd_file($)
8593{
8594 my $Path = $_[0];
8595 return "" if(not $Path or not -e $Path);
8596 if(my $CmdPath = get_CmdPath("file")) {
8597 return `$CmdPath -b \"$Path\"`;
8598 }
8599 return "";
8600}
8601
8602sub getIncString($$)
8603{
8604 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008605 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008606 my $String = "";
8607 foreach (@{$ArrRef}) {
8608 $String .= " ".inc_opt($_, $Style);
8609 }
8610 return $String;
8611}
8612
8613sub getIncPaths(@)
8614{
8615 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008616 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008617 if($INC_PATH_AUTODETECT{$Version})
8618 { # auto-detecting dependencies
8619 my %Includes = ();
8620 foreach my $HPath (@HeaderPaths)
8621 {
8622 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8623 {
8624 if($Skip_Include_Paths{$Version}{$Dir}) {
8625 next;
8626 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008627 if($SystemRoot)
8628 {
8629 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8630 next;
8631 }
8632 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008633 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008634 }
8635 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008636 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008637 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008638 }
8639 }
8640 else
8641 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008642 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008643 }
8644 return \@IncPaths;
8645}
8646
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008647sub push_U($@)
8648{ # push unique
8649 if(my $Array = shift @_)
8650 {
8651 if(@_)
8652 {
8653 my %Exist = map {$_=>1} @{$Array};
8654 foreach my $Elem (@_)
8655 {
8656 if(not defined $Exist{$Elem})
8657 {
8658 push(@{$Array}, $Elem);
8659 $Exist{$Elem} = 1;
8660 }
8661 }
8662 }
8663 }
8664}
8665
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008666sub callPreprocessor($$$)
8667{
8668 my ($Path, $Inc, $LibVersion) = @_;
8669 return "" if(not $Path or not -f $Path);
8670 my $IncludeString=$Inc;
8671 if(not $Inc) {
8672 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8673 }
8674 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008675 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008676 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008677 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008678}
8679
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008680sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008681{ # native "find" is much faster than File::Find (~6x)
8682 # also the File::Find doesn't support --maxdepth N option
8683 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008684 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008685 return () if(not $Path or not -e $Path);
8686 if($OSgroup eq "windows")
8687 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008688 $Path = get_abs_path($Path);
8689 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008690 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008691 if($MaxDepth!=1) {
8692 $Cmd .= " /S";
8693 }
8694 if($Type eq "d") {
8695 $Cmd .= " /AD";
8696 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008697 elsif($Type eq "f") {
8698 $Cmd .= " /A-D";
8699 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008700 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008701 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008702 {
8703 if(not $UseRegex)
8704 { # FIXME: how to search file names in MS shell?
8705 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008706 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008707 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008708 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008709 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008710 }
8711 my @AbsPaths = ();
8712 foreach my $File (@Files)
8713 {
8714 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008715 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008716 }
8717 if($Type eq "f" and not -f $File)
8718 { # skip dirs
8719 next;
8720 }
8721 push(@AbsPaths, path_format($File, $OSgroup));
8722 }
8723 if($Type eq "d") {
8724 push(@AbsPaths, $Path);
8725 }
8726 return @AbsPaths;
8727 }
8728 else
8729 {
8730 my $FindCmd = get_CmdPath("find");
8731 if(not $FindCmd) {
8732 exitStatus("Not_Found", "can't find a \"find\" command");
8733 }
8734 $Path = get_abs_path($Path);
8735 if(-d $Path and -l $Path
8736 and $Path!~/\/\Z/)
8737 { # for directories that are symlinks
8738 $Path.="/";
8739 }
8740 my $Cmd = $FindCmd." \"$Path\"";
8741 if($MaxDepth) {
8742 $Cmd .= " -maxdepth $MaxDepth";
8743 }
8744 if($Type) {
8745 $Cmd .= " -type $Type";
8746 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008747 if($Name and not $UseRegex)
8748 { # wildcards
8749 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008750 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008751 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008752 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008753 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8754 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008755 my @Files = split(/\n/, $Res);
8756 if($Name and $UseRegex)
8757 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008758 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008759 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008760 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008761 }
8762}
8763
8764sub unpackDump($)
8765{
8766 my $Path = $_[0];
8767 return "" if(not $Path or not -e $Path);
8768 $Path = get_abs_path($Path);
8769 $Path = path_format($Path, $OSgroup);
8770 my ($Dir, $FileName) = separate_path($Path);
8771 my $UnpackDir = $TMP_DIR."/unpack";
8772 rmtree($UnpackDir);
8773 mkpath($UnpackDir);
8774 if($FileName=~s/\Q.zip\E\Z//g)
8775 { # *.zip
8776 my $UnzipCmd = get_CmdPath("unzip");
8777 if(not $UnzipCmd) {
8778 exitStatus("Not_Found", "can't find \"unzip\" command");
8779 }
8780 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008781 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008782 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008783 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008784 }
8785 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008786 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008787 if(not @Contents) {
8788 exitStatus("Error", "can't extract \'$Path\'");
8789 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008790 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008791 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008792 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008793 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008794 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008795 if($OSgroup eq "windows")
8796 { # -xvzf option is not implemented in tar.exe (2003)
8797 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8798 my $TarCmd = get_CmdPath("tar");
8799 if(not $TarCmd) {
8800 exitStatus("Not_Found", "can't find \"tar\" command");
8801 }
8802 my $GzipCmd = get_CmdPath("gzip");
8803 if(not $GzipCmd) {
8804 exitStatus("Not_Found", "can't find \"gzip\" command");
8805 }
8806 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008807 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008808 if($?) {
8809 exitStatus("Error", "can't extract \'$Path\'");
8810 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008811 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008812 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008813 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008814 }
8815 chdir($ORIG_DIR);
8816 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008817 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008818 if(not @Contents) {
8819 exitStatus("Error", "can't extract \'$Path\'");
8820 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008821 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008822 }
8823 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008824 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008825 my $TarCmd = get_CmdPath("tar");
8826 if(not $TarCmd) {
8827 exitStatus("Not_Found", "can't find \"tar\" command");
8828 }
8829 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008830 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008831 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008832 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008833 }
8834 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008835 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008836 if(not @Contents) {
8837 exitStatus("Error", "can't extract \'$Path\'");
8838 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008839 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008840 }
8841 }
8842}
8843
8844sub createArchive($$)
8845{
8846 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008847 if(not $To) {
8848 $To = ".";
8849 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008850 if(not $Path or not -e $Path
8851 or not -d $To) {
8852 return "";
8853 }
8854 my ($From, $Name) = separate_path($Path);
8855 if($OSgroup eq "windows")
8856 { # *.zip
8857 my $ZipCmd = get_CmdPath("zip");
8858 if(not $ZipCmd) {
8859 exitStatus("Not_Found", "can't find \"zip\"");
8860 }
8861 my $Pkg = $To."/".$Name.".zip";
8862 unlink($Pkg);
8863 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008864 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008865 if($?)
8866 { # cannot allocate memory (or other problems with "zip")
8867 unlink($Path);
8868 exitStatus("Error", "can't pack the ABI dump: ".$!);
8869 }
8870 chdir($ORIG_DIR);
8871 unlink($Path);
8872 return $Pkg;
8873 }
8874 else
8875 { # *.tar.gz
8876 my $TarCmd = get_CmdPath("tar");
8877 if(not $TarCmd) {
8878 exitStatus("Not_Found", "can't find \"tar\"");
8879 }
8880 my $GzipCmd = get_CmdPath("gzip");
8881 if(not $GzipCmd) {
8882 exitStatus("Not_Found", "can't find \"gzip\"");
8883 }
8884 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8885 unlink($Pkg);
8886 chdir($From);
8887 system($TarCmd, "-czf", $Pkg, $Name);
8888 if($?)
8889 { # cannot allocate memory (or other problems with "tar")
8890 unlink($Path);
8891 exitStatus("Error", "can't pack the ABI dump: ".$!);
8892 }
8893 chdir($ORIG_DIR);
8894 unlink($Path);
8895 return $To."/".$Name.".tar.gz";
8896 }
8897}
8898
8899sub is_header_file($)
8900{
8901 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8902 return $_[0];
8903 }
8904 return 0;
8905}
8906
8907sub is_not_header($)
8908{
8909 if($_[0]=~/\.\w+\Z/
8910 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8911 return 1;
8912 }
8913 return 0;
8914}
8915
8916sub is_header($$$)
8917{
8918 my ($Header, $UserDefined, $LibVersion) = @_;
8919 return 0 if(-d $Header);
8920 if(-f $Header) {
8921 $Header = get_abs_path($Header);
8922 }
8923 else
8924 {
8925 if(is_abs($Header))
8926 { # incorrect absolute path
8927 return 0;
8928 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008929 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008930 $Header = $HPath;
8931 }
8932 else
8933 { # can't find header
8934 return 0;
8935 }
8936 }
8937 if($Header=~/\.\w+\Z/)
8938 { # have an extension
8939 return is_header_file($Header);
8940 }
8941 else
8942 {
8943 if($UserDefined==2)
8944 { # specified on the command line
8945 if(cmd_file($Header)!~/HTML|XML/i) {
8946 return $Header;
8947 }
8948 }
8949 elsif($UserDefined)
8950 { # specified in the XML-descriptor
8951 # header file without an extension
8952 return $Header;
8953 }
8954 else
8955 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008956 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008957 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008958 { # !~/HTML|XML|shared|dynamic/i
8959 return $Header;
8960 }
8961 }
8962 }
8963 return 0;
8964}
8965
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008966sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008967{
8968 my $LibVersion = $_[0];
8969 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
8970 {
8971 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008972 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008973
8974 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
8975 detect_recursive_includes($RegHeader, $LibVersion);
8976 }
8977
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008978 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
8979 {
8980 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008981
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04008982 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008983 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
8984 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008985 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008986 }
8987 }
8988 }
8989}
8990
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008991sub familiarDirs($$)
8992{
8993 my ($D1, $D2) = @_;
8994 if($D1 eq $D2) {
8995 return 1;
8996 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04008997
8998 my $U1 = index($D1, "/usr/");
8999 my $U2 = index($D2, "/usr/");
9000
9001 if($U1==0 and $U2!=0) {
9002 return 0;
9003 }
9004
9005 if($U2==0 and $U1!=0) {
9006 return 0;
9007 }
9008
9009 if(index($D2, $D1."/")==0) {
9010 return 1;
9011 }
9012
9013 # /usr/include/DIR
9014 # /home/user/DIR
9015
9016 my $DL = get_depth($D1);
9017
9018 my @Dirs1 = ($D1);
9019 while($DL - get_depth($D1)<=2
9020 and get_depth($D1)>=4
9021 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9022 push(@Dirs1, $D1);
9023 }
9024
9025 my @Dirs2 = ($D2);
9026 while(get_depth($D2)>=4
9027 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9028 push(@Dirs2, $D2);
9029 }
9030
9031 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009032 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009033 foreach my $P2 (@Dirs2)
9034 {
9035
9036 if($P1 eq $P2) {
9037 return 1;
9038 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009039 }
9040 }
9041 return 0;
9042}
9043
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009044sub readHeaders($)
9045{
9046 $Version = $_[0];
9047 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9048 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009049 if($Debug)
9050 { # debug mode
9051 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009052 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009053 }
9054 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009055}
9056
9057sub prepareTypes($)
9058{
9059 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009060 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009061 { # support for old ABI dumps
9062 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009063 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009064 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009065 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9066 if($TName=~/\A(\w+)::(\w+)/) {
9067 my ($P1, $P2) = ($1, $2);
9068 if($P1 eq $P2) {
9069 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009070 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009071 else {
9072 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9073 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009074 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009075 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009076 }
9077 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009078 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009079 { # support for old ABI dumps
9080 # V < 2.5: array size == "number of elements"
9081 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009082 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009083 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009084 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009085 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009086 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009087 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009088 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009089 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009090 $Size *= $Base{"Size"};
9091 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009092 }
9093 else
9094 { # array[] is a pointer
9095 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009096 }
9097 }
9098 }
9099 }
9100 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009101 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009102 { # support for old ABI dumps
9103 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009104 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009105 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009106 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009107 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009108 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009109 my %Type = get_Type($TypeId, $LibVersion);
9110 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9111 my %Type2 = get_Type($TypeId_2, $V2);
9112 if($Type{"Size"} ne $Type2{"Size"}) {
9113 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009114 }
9115 }
9116 }
9117 }
9118}
9119
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009120sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009121{
9122 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009123
9124 if(not keys(%{$SymbolInfo{$LibVersion}}))
9125 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009126 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009127 {
9128 if($CheckHeadersOnly) {
9129 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9130 }
9131 else {
9132 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9133 }
9134 }
9135 }
9136
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009137 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009138 if(not checkDump(1, "2.10")
9139 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009140 { # different formats
9141 $Remangle = 1;
9142 }
9143 if($CheckHeadersOnly)
9144 { # different languages
9145 if($UserLang)
9146 { # --lang=LANG for both versions
9147 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9148 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9149 {
9150 if($UserLang eq "C++")
9151 { # remangle symbols
9152 $Remangle = 1;
9153 }
9154 elsif($UserLang eq "C")
9155 { # remove mangling
9156 $Remangle = -1;
9157 }
9158 }
9159 }
9160 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009161
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009162 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009163 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009164 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009165 { # support for old ABI dumps
9166 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9167 {
9168 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9169 {
9170 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9171 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009172 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009173 if(defined $DVal and $DVal ne "")
9174 {
9175 if($TName eq "char") {
9176 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9177 }
9178 elsif($TName eq "bool") {
9179 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9180 }
9181 }
9182 }
9183 }
9184 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009185 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009186 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009187 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9188 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009189 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009190 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9191 # + support for old ABI dumps
9192 next;
9193 }
9194 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009195 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009196 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009197 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009198 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009199
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009200 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009201 if(not checkDump(1, "2.12")
9202 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009203 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009204 if($ShortName eq "operator>>")
9205 {
9206 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9207 { # corrected mangling of operator>>
9208 $SRemangle = 1;
9209 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009210 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009211 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9212 {
9213 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9214 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9215 { # corrected mangling of const global data
9216 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9217 # and incorrectly mangled by old ACC versions
9218 $SRemangle = 1;
9219 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009220 }
9221 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009222 if(not $CheckHeadersOnly)
9223 { # support for old ABI dumps
9224 if(not checkDump(1, "2.17")
9225 or not checkDump(2, "2.17"))
9226 {
9227 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9228 {
9229 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9230 {
9231 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9232 {
9233 $MnglName = $ShortName;
9234 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9235 }
9236 }
9237 }
9238 }
9239 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009240 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009241 { # support for old ABI dumps: some symbols are not mangled in old dumps
9242 # mangle both sets of symbols (old and new)
9243 # NOTE: remangling all symbols by the same mangler
9244 if($MnglName=~/\A_ZN(V|)K/)
9245 { # mangling may be incorrect on old ABI dumps
9246 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009247 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009248 }
9249 if($MnglName=~/\A_ZN(K|)V/)
9250 { # mangling may be incorrect on old ABI dumps
9251 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009252 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009253 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009254 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9255 or (not $ClassID and $CheckHeadersOnly)
9256 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9257 { # support for old ABI dumps, GCC >= 4.0
9258 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009259 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009260 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009261 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009262 $MangledNames{$LibVersion}{$MnglName} = 1;
9263 }
9264 }
9265 }
9266 elsif($Remangle==-1)
9267 { # remove mangling
9268 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009269 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009270 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009271 if(not $MnglName) {
9272 next;
9273 }
9274 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9275 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009276 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9277
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009278 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009279 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009280 { # support for old dumps
9281 # add "Volatile" attribute
9282 if($MnglName=~/_Z(K|)V/) {
9283 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9284 }
9285 }
9286 # symbol and its symlink have same signatures
9287 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009288 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009289 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009290
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009291 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9292 {
9293 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9294 if($SymVer{$LibVersion}{$Alias}) {
9295 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9296 }
9297 }
9298
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009299 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009300 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009301 }
9302 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9303 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9304 }
9305 if($ExtendedCheck)
9306 { # --ext option
9307 addExtension($LibVersion);
9308 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009309
9310 # clean memory
9311 delete($SymbolInfo{$LibVersion});
9312
9313 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009314 { # detect allocable classes with public exported constructors
9315 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009316 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009317 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009318 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009319 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009320 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9321 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009322 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009323 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009324 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009325 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009326 $AllocableClass{$LibVersion}{$ClassName} = 1;
9327 }
9328 }
9329 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009330 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009331 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009332 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009333 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009334 if($CheckHeadersOnly)
9335 {
9336 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9337 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9338 { # all symbols except non-virtual inline
9339 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9340 }
9341 }
9342 else {
9343 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009344 }
9345 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009346 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009347 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009348 }
9349 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009350 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009351 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009352 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009353 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009354 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009355 if(defined $Base{"Type"}
9356 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009357 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009358 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009359 if($Name=~/<([^<>\s]+)>/)
9360 {
9361 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9362 $ReturnedClass{$LibVersion}{$Tid} = 1;
9363 }
9364 }
9365 else {
9366 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9367 }
9368 }
9369 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009370 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009371 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009372 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009373 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009374 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009375 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009376 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009377 if($Base{"Type"}=~/Struct|Class/)
9378 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009379 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009380 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9381 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009382 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009383 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009384 }
9385 }
9386 }
9387 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009388
9389 # mapping {short name => symbols}
9390 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009391 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009392 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009393 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009394 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009395 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009396 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009397 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009398 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9399 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009400 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009401 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009402 }
9403 }
9404 }
9405 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009406
9407 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009408 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009409 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009410 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009411 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009412 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9413 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009414 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009415 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009416 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009417 $ClassNames{$LibVersion}{$TName} = 1;
9418 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009419 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009420 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9421 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009422 }
9423 }
9424 }
9425 }
9426 }
9427}
9428
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009429sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009430{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009431 my ($Tid, $LibVersion) = @_;
9432 if(not $Tid) {
9433 return $Tid;
9434 }
9435
9436 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9437 {
9438 if($TName_Tid{$LibVersion}{$Name}) {
9439 return $TName_Tid{$LibVersion}{$Name};
9440 }
9441 }
9442
9443 return $Tid;
9444}
9445
9446sub register_SymbolUsage($$$)
9447{
9448 my ($InfoId, $UsedType, $LibVersion) = @_;
9449
9450 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9451 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9452 {
9453 register_TypeUsage($RTid, $UsedType, $LibVersion);
9454 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9455 }
9456 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9457 {
9458 register_TypeUsage($FCid, $UsedType, $LibVersion);
9459 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9460
9461 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9462 { # register "this" pointer
9463 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9464 }
9465 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9466 { # register "this" pointer (const method)
9467 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9468 }
9469 }
9470 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9471 {
9472 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9473 {
9474 register_TypeUsage($PTid, $UsedType, $LibVersion);
9475 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9476 }
9477 }
9478 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9479 {
9480 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9481 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9482 register_TypeUsage($TTid, $UsedType, $LibVersion);
9483 }
9484 }
9485}
9486
9487sub register_TypeUsage($$$)
9488{
9489 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009490 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009491 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009492 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009493 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009494 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009495 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009496 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009497
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009498 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009499 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009500 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009501 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009502 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009503 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9504 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9505 }
9506 }
9507
9508 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9509 {
9510 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009511 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009512 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009513 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9514 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009515 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009516 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9517 {
9518 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9519 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009520 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009521 }
9522 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009523 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009524 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009525 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009526 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9527 {
9528 register_TypeUsage($MTid, $UsedType, $LibVersion);
9529 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009530 }
9531 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009532 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009533 or $TInfo{"Type"} eq "MethodPtr"
9534 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009535 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009536 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009537 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009538 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009539 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009540 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009541 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9542 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009543 }
9544 }
9545 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009546 if($TInfo{"Type"} eq "FieldPtr")
9547 {
9548 if(my $RTid = $TInfo{"Return"}) {
9549 register_TypeUsage($RTid, $UsedType, $LibVersion);
9550 }
9551 if(my $CTid = $TInfo{"Class"}) {
9552 register_TypeUsage($CTid, $UsedType, $LibVersion);
9553 }
9554 }
9555 if($TInfo{"Type"} eq "MethodPtr")
9556 {
9557 if(my $CTid = $TInfo{"Class"}) {
9558 register_TypeUsage($CTid, $UsedType, $LibVersion);
9559 }
9560 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009561 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009562 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009563 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009564 $UsedType->{$TypeId} = 1;
9565 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9566 {
9567 register_TypeUsage($BTid, $UsedType, $LibVersion);
9568 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9569 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009570 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009571 else
9572 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9573 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009574 }
9575 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009576}
9577
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009578sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009579{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009580 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9581
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009582 if($Level eq "Dump")
9583 {
9584 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9585 { # TODO: check if this symbol is from
9586 # base classes of other target symbols
9587 return 1;
9588 }
9589 }
9590
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009591 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9592 { # stdc++ interfaces
9593 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009594 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009595
9596 my $Target = 0;
9597 if(my $Header = $SInfo->{"Header"}) {
9598 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9599 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009600 if($ExtendedCheck)
9601 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009602 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009603 $Target = 1;
9604 }
9605 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009606 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009607 {
9608 if($Target)
9609 {
9610 if($Level eq "Dump")
9611 { # dumped
9612 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009613 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009614 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009615 return 1;
9616 }
9617 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009618 else {
9619 return 1;
9620 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009621 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009622 elsif($Level eq "Source")
9623 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009624 return 1;
9625 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009626 elsif($Level eq "Binary")
9627 { # checked
9628 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9629 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9630 return 1;
9631 }
9632 }
9633 }
9634 }
9635 else
9636 { # library is available
9637 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9638 { # exported symbols
9639 return 1;
9640 }
9641 if($Level eq "Dump")
9642 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009643 if($BinaryOnly)
9644 {
9645 if($SInfo->{"Data"})
9646 {
9647 if($Target) {
9648 return 1;
9649 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009650 }
9651 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009652 else
9653 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009654 if($Target) {
9655 return 1;
9656 }
9657 }
9658 }
9659 elsif($Level eq "Source")
9660 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009661 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009662 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009663 { # skip LOCAL symbols
9664 if($Target) {
9665 return 1;
9666 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009667 }
9668 }
9669 elsif($Level eq "Binary")
9670 { # checked
9671 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9672 {
9673 if($Target) {
9674 return 1;
9675 }
9676 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009677 }
9678 }
9679 return 0;
9680}
9681
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009682sub cleanDump($)
9683{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009684 my $LibVersion = $_[0];
9685 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9686 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009687 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9688 {
9689 delete($SymbolInfo{$LibVersion}{$InfoId});
9690 next;
9691 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009692 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009693 if(not $MnglName)
9694 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009695 delete($SymbolInfo{$LibVersion}{$InfoId});
9696 next;
9697 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009698 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009699 if(not $ShortName)
9700 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009701 delete($SymbolInfo{$LibVersion}{$InfoId});
9702 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009703 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009704 if($MnglName eq $ShortName)
9705 { # remove duplicate data
9706 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009707 }
9708 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9709 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9710 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009711 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9712 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9713 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009714 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009715 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009716 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009717 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009718 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9719 {
9720 delete($TypeInfo{$LibVersion}{$Tid});
9721 next;
9722 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009723 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009724 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009725 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009726 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9727 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9728 }
9729 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009730 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9731 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9732 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009733 }
9734}
9735
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009736sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009737{
9738 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009739
9740 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9741 {
9742 if(defined $TypeInfo{$LibVersion}{$Dupl})
9743 {
9744 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9745 { # duplicate
9746 return 0;
9747 }
9748 }
9749 }
9750
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009751 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9752
9753 if(isBuiltIn($THeader)) {
9754 return 0;
9755 }
9756
9757 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9758 return 0;
9759 }
9760
9761 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9762 return 0;
9763 }
9764
9765 if(selfTypedef($Tid, $LibVersion)) {
9766 return 0;
9767 }
9768
9769 if(not isTargetType($Tid, $LibVersion)) {
9770 return 0;
9771 }
9772
9773 return 0;
9774}
9775
9776sub isTargetType($$)
9777{
9778 my ($Tid, $LibVersion) = @_;
9779
9780 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9781 { # derived
9782 return 1;
9783 }
9784
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009785 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9786 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009787 if(not is_target_header($THeader, $LibVersion))
9788 { # from target headers
9789 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009790 }
9791 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +03009792 else {
9793 return 0;
9794 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009795
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +03009796 if($SkipInternalTypes)
9797 {
9798 if($TypeInfo{$LibVersion}{$Tid}{"Name"}=~/($SkipInternalTypes)/)
9799 {
9800 return 0;
9801 }
9802 }
9803
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009804 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009805}
9806
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009807sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009808{ # remove unused data types from the ABI dump
9809 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009810
9811 my %UsedType = ();
9812
9813 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009814 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009815 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009816 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009817 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009818 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009819 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009820 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009821 next;
9822 }
9823
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009824 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009825 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009826 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009827 {
9828 my %Tree = ();
9829 register_TypeUsage($Tid, \%Tree, $LibVersion);
9830
9831 my $Tmpl = 0;
9832 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9833 {
9834 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9835 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9836 {
9837 $Tmpl = 1;
9838 last;
9839 }
9840 }
9841 if(not $Tmpl)
9842 {
9843 foreach (keys(%Tree)) {
9844 $UsedType{$_} = 1;
9845 }
9846 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009847 }
9848 }
9849 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009850
9851 my %Delete = ();
9852
9853 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009854 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009855 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009856 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009857 next;
9858 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009859
9860 if($Kind eq "Extra")
9861 {
9862 my %Tree = ();
9863 register_TypeUsage($Tid, \%Tree, $LibVersion);
9864
9865 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9866 {
9867 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9868 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9869 {
9870 $Delete{$Tid} = 1;
9871 last;
9872 }
9873 }
9874 }
9875 else
9876 {
9877 # remove type
9878 delete($TypeInfo{$LibVersion}{$Tid});
9879 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009880 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009881
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009882 if($Kind eq "Extra")
9883 { # remove duplicates
9884 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9885 {
9886 if($UsedType{$Tid})
9887 { # All & Extended
9888 next;
9889 }
9890
9891 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9892
9893 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9894 delete($TypeInfo{$LibVersion}{$Tid});
9895 }
9896 }
9897 }
9898
9899 foreach my $Tid (keys(%Delete))
9900 {
9901 delete($TypeInfo{$LibVersion}{$Tid});
9902 }
9903}
9904
9905sub check_Completeness($$)
9906{
9907 my ($Info, $LibVersion) = @_;
9908
9909 # data types
9910 if(defined $Info->{"Memb"})
9911 {
9912 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9913 {
9914 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9915 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9916 }
9917 }
9918 }
9919 if(defined $Info->{"Base"})
9920 {
9921 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9922 check_TypeInfo($Bid, $LibVersion);
9923 }
9924 }
9925 if(defined $Info->{"BaseType"}) {
9926 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9927 }
9928 if(defined $Info->{"TParam"})
9929 {
9930 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9931 {
9932 my $TName = $Info->{"TParam"}{$Pos}{"name"};
9933 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
9934 next;
9935 }
9936 if($TName eq "_BoolType") {
9937 next;
9938 }
9939 if($TName=~/\Asizeof\(/) {
9940 next;
9941 }
9942 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
9943 check_TypeInfo($Tid, $LibVersion);
9944 }
9945 else
9946 {
9947 if(defined $Debug) {
9948 printMsg("WARNING", "missed type $TName");
9949 }
9950 }
9951 }
9952 }
9953
9954 # symbols
9955 if(defined $Info->{"Param"})
9956 {
9957 foreach my $Pos (keys(%{$Info->{"Param"}}))
9958 {
9959 if(defined $Info->{"Param"}{$Pos}{"type"}) {
9960 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
9961 }
9962 }
9963 }
9964 if(defined $Info->{"Return"}) {
9965 check_TypeInfo($Info->{"Return"}, $LibVersion);
9966 }
9967 if(defined $Info->{"Class"}) {
9968 check_TypeInfo($Info->{"Class"}, $LibVersion);
9969 }
9970}
9971
9972sub check_TypeInfo($$)
9973{
9974 my ($Tid, $LibVersion) = @_;
9975
9976 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
9977 return;
9978 }
9979 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
9980
9981 if(defined $TypeInfo{$LibVersion}{$Tid})
9982 {
9983 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
9984 printMsg("ERROR", "missed type name ($Tid)");
9985 }
9986 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
9987 }
9988 else {
9989 printMsg("ERROR", "missed type id $Tid");
9990 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009991}
9992
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009993sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009994{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009995 my ($TypeId, $LibVersion) = @_;
9996 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009997 if($Type{"Type"} eq "Typedef")
9998 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009999 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010000 if($Base{"Type"}=~/Class|Struct/)
10001 {
10002 if($Type{"Name"} eq $Base{"Name"}) {
10003 return 1;
10004 }
10005 elsif($Type{"Name"}=~/::(\w+)\Z/)
10006 {
10007 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10008 { # QPointer<QWidget>::QPointer
10009 return 1;
10010 }
10011 }
10012 }
10013 }
10014 return 0;
10015}
10016
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010017sub addExtension($)
10018{
10019 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010020 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010021 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +030010022 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010023 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010024 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10025 $TName=~s/\A(struct|union|class|enum) //;
10026 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010027
10028 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10029 "Header" => "extended.h",
10030 "ShortName" => $Symbol,
10031 "MnglName" => $Symbol,
10032 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10033 );
10034
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010035 $ExtendedSymbols{$Symbol} = 1;
10036 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10037 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010038 }
10039 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010040 $ExtendedSymbols{"external_func_0"} = 1;
10041 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10042 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010043}
10044
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010045sub findMethod($$$)
10046{
10047 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010048 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010049 {
10050 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10051 return $VirtMethodInClass;
10052 }
10053 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10054 return $VirtMethodInBaseClasses;
10055 }
10056 }
10057 return "";
10058}
10059
10060sub findMethod_Class($$$)
10061{
10062 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010063 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010064 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10065 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10066 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10067 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10068 { # search for interface with the same parameters suffix (overridden)
10069 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10070 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010071 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10072 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010073 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10074 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010075 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10076 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10077 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10078 return $Candidate;
10079 }
10080 }
10081 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010082 else
10083 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010084 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10085 return $Candidate;
10086 }
10087 }
10088 }
10089 }
10090 return "";
10091}
10092
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010093sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010094{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010095 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010096 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010097 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010098 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10099 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010100 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010101 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010102 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010103 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10104 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010105 { # pure virtual D2-destructors are marked as "virt" in the dump
10106 # virtual D2-destructors are NOT marked as "virt" in the dump
10107 # both destructors are not presented in the v-table
10108 next;
10109 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010110 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010111 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10112 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010113 }
10114}
10115
10116sub registerOverriding($)
10117{
10118 my $LibVersion = $_[0];
10119 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010120 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010121 foreach my $ClassName (@Classes)
10122 {
10123 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10124 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010125 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10126 { # pure virtuals
10127 next;
10128 }
10129 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10130 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010131 {
10132 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10133 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10134 { # both overridden virtual methods
10135 # and implemented pure virtual methods
10136 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10137 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10138 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10139 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010140 }
10141 }
10142 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10143 delete($VirtualTable{$LibVersion}{$ClassName});
10144 }
10145 }
10146}
10147
10148sub setVirtFuncPositions($)
10149{
10150 my $LibVersion = $_[0];
10151 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10152 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010153 my ($Num, $Rel) = (1, 0);
10154
10155 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010156 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010157 if($UsedDump{$LibVersion}{"DWARF"}) {
10158 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10159 }
10160 else {
10161 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10162 }
10163 foreach my $VirtFunc (@Funcs)
10164 {
10165 if($UsedDump{$LibVersion}{"DWARF"}) {
10166 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10167 }
10168 else {
10169 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10170 }
10171
10172 # set relative positions
10173 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10174 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10175 { # relative position excluding added and removed virtual functions
10176 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10177 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10178 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10179 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010180 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010181 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010182 }
10183 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010184 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010185 {
10186 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010187 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010188 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010189 }
10190 }
10191}
10192
10193sub get_sub_classes($$$)
10194{
10195 my ($ClassId, $LibVersion, $Recursive) = @_;
10196 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10197 my @Subs = ();
10198 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10199 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010200 if($Recursive)
10201 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010202 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10203 push(@Subs, $SubSubId);
10204 }
10205 }
10206 push(@Subs, $SubId);
10207 }
10208 return @Subs;
10209}
10210
10211sub get_base_classes($$$)
10212{
10213 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010214 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010215 return () if(not defined $ClassType{"Base"});
10216 my @Bases = ();
10217 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10218 keys(%{$ClassType{"Base"}}))
10219 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010220 if($Recursive)
10221 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010222 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10223 push(@Bases, $SubBaseId);
10224 }
10225 }
10226 push(@Bases, $BaseId);
10227 }
10228 return @Bases;
10229}
10230
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010231sub getVTable_Model($$)
10232{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010233 my ($ClassId, $LibVersion) = @_;
10234 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10235 my @Elements = ();
10236 foreach my $BaseId (@Bases, $ClassId)
10237 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010238 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010239 {
10240 if(defined $VirtualTable{$LibVersion}{$BName})
10241 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010242 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10243 if($UsedDump{$LibVersion}{"DWARF"}) {
10244 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10245 }
10246 else {
10247 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10248 }
10249 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010250 push(@Elements, $VFunc);
10251 }
10252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010253 }
10254 }
10255 return @Elements;
10256}
10257
10258sub getVShift($$)
10259{
10260 my ($ClassId, $LibVersion) = @_;
10261 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10262 my $VShift = 0;
10263 foreach my $BaseId (@Bases)
10264 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010265 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010266 {
10267 if(defined $VirtualTable{$LibVersion}{$BName}) {
10268 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10269 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010270 }
10271 }
10272 return $VShift;
10273}
10274
10275sub getShift($$)
10276{
10277 my ($ClassId, $LibVersion) = @_;
10278 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10279 my $Shift = 0;
10280 foreach my $BaseId (@Bases)
10281 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010282 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010283 {
10284 if($Size!=1)
10285 { # not empty base class
10286 $Shift+=$Size;
10287 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010288 }
10289 }
10290 return $Shift;
10291}
10292
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010293sub getVTable_Size($$)
10294{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010295 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010296 my $Size = 0;
10297 # three approaches
10298 if(not $Size)
10299 { # real size
10300 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10301 $Size = keys(%VTable);
10302 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010303 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010304 if(not $Size)
10305 { # shared library symbol size
10306 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10307 $Size /= $WORD_SIZE{$LibVersion};
10308 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010309 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010310 if(not $Size)
10311 { # model size
10312 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10313 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10314 }
10315 }
10316 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010317}
10318
10319sub isCopyingClass($$)
10320{
10321 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010322 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010323}
10324
10325sub isLeafClass($$)
10326{
10327 my ($ClassId, $LibVersion) = @_;
10328 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10329}
10330
10331sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010332{ # check structured type for public fields
10333 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010334}
10335
10336sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010337{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010338 my ($TypePtr, $Skip, $Start, $End) = @_;
10339 return 0 if(not $TypePtr);
10340 if($End==-1) {
10341 $End = keys(%{$TypePtr->{"Memb"}})-1;
10342 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030010343 foreach my $MemPos (sort {int($a)<=>int($b)} keys(%{$TypePtr->{"Memb"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010344 {
10345 if($Skip and $Skip->{$MemPos})
10346 { # skip removed/added fields
10347 next;
10348 }
10349 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10350 {
10351 if(isPublic($TypePtr, $MemPos)) {
10352 return ($MemPos+1);
10353 }
10354 }
10355 }
10356 return 0;
10357}
10358
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010359sub isReserved($)
10360{ # reserved fields == private
10361 my $MName = $_[0];
10362 if($MName=~/reserved|padding|f_spare/i) {
10363 return 1;
10364 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010365 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010366 return 1;
10367 }
10368 if($MName=~/(pad\d+)/i) {
10369 return 1;
10370 }
10371 return 0;
10372}
10373
10374sub isPublic($$)
10375{
10376 my ($TypePtr, $FieldPos) = @_;
10377 return 0 if(not $TypePtr);
10378 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10379 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10380 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10381 { # by name in C language
10382 # FIXME: add other methods to detect private members
10383 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10384 if($MName=~/priv|abidata|parent_object/i)
10385 { # C-styled private data
10386 return 0;
10387 }
10388 if(lc($MName) eq "abi")
10389 { # ABI information/reserved field
10390 return 0;
10391 }
10392 if(isReserved($MName))
10393 { # reserved fields
10394 return 0;
10395 }
10396 return 1;
10397 }
10398 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10399 { # by access in C++ language
10400 return 1;
10401 }
10402 return 0;
10403}
10404
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010405sub getVTable_Real($$)
10406{
10407 my ($ClassName, $LibVersion) = @_;
10408 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10409 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010410 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010411 if(defined $Type{"VTable"}) {
10412 return %{$Type{"VTable"}};
10413 }
10414 }
10415 return ();
10416}
10417
10418sub cmpVTables($)
10419{
10420 my $ClassName = $_[0];
10421 my $Res = cmpVTables_Real($ClassName, 1);
10422 if($Res==-1) {
10423 $Res = cmpVTables_Model($ClassName);
10424 }
10425 return $Res;
10426}
10427
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010428sub cmpVTables_Model($)
10429{
10430 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010431 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010432 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010433 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010434 return 1;
10435 }
10436 }
10437 return 0;
10438}
10439
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010440sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010441{
10442 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010443 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10444 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010445 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010446 my %VTable_Old = getVTable_Real($ClassName, 1);
10447 my %VTable_New = getVTable_Real($ClassName, 2);
10448 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010449 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010450 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010451 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010452 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010453 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10454 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010455 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010456 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010457 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010458 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010459 my $Entry1 = $VTable_Old{$Offset};
10460 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010461 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010462 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010463 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010464 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010465
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010466 $Entry1 = simpleVEntry($Entry1);
10467 $Entry2 = simpleVEntry($Entry2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010468
10469 if($Entry1=~/ 0x/ and $Entry2=~/ 0x/)
10470 { # NOTE: problem with vtable-dumper
10471 next;
10472 }
10473
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010474 if($Entry1 ne $Entry2)
10475 { # register as changed
10476 if($Entry1=~/::([^:]+)\Z/)
10477 {
10478 my $M1 = $1;
10479 if($Entry2=~/::([^:]+)\Z/)
10480 {
10481 my $M2 = $1;
10482 if($M1 eq $M2)
10483 { # overridden
10484 next;
10485 }
10486 }
10487 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010488 if(differentDumps("G"))
10489 {
10490 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10491 {
10492 # GCC 4.6.1: -0x00000000000000010
10493 # GCC 4.7.0: -16
10494 next;
10495 }
10496 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010497 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010498 }
10499 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010500 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010501}
10502
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010503sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010504{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010505 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010506 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10507 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010508 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010509 { # already registered
10510 next;
10511 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010512 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010513 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010514 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010515 foreach my $Symbol (@Affected)
10516 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010517 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010518 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010519 "Target"=>$ClassName);
10520 }
10521 }
10522 }
10523}
10524
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010525sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010526{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010527 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010528 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010529 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010530 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010531 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010532 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010533 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010534 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010535 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010536 if($TName_Tid{1}{$ClassName}
10537 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010538 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010539 if(defined $CompleteSignature{1}{$Symbol}
10540 and $CompleteSignature{1}{$Symbol}{"Virt"})
10541 { # override some method in v.1
10542 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010543 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010544 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010545 }
10546 }
10547 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010548 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010549 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010550 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010551 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010552 if($TName_Tid{2}{$ClassName}
10553 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010554 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010555 if(defined $CompleteSignature{2}{$Symbol}
10556 and $CompleteSignature{2}{$Symbol}{"Virt"})
10557 { # override some method in v.2
10558 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010559 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010560 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010561 }
10562 }
10563 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010564 if($Level eq "Binary")
10565 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010566 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010567 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10568 { # check replacements, including pure virtual methods
10569 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10570 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010571 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010572 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10573 if($AddedPos==$RemovedPos)
10574 {
10575 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10576 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10577 last; # other methods will be reported as "added" or "removed"
10578 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010579 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010580 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10581 {
10582 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10583 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010584 next;
10585 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010586 my $ProblemType = "Virtual_Replacement";
10587 my @Affected = ($RemovedVFunc);
10588 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10589 { # pure methods
10590 if(not isUsedClass($ClassId, 1, $Level))
10591 { # not a parameter of some exported method
10592 next;
10593 }
10594 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010595
10596 # affected all methods (both virtual and non-virtual ones)
10597 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10598 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010599 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010600 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010601 foreach my $AffectedInt (@Affected)
10602 {
10603 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10604 { # affected exported methods only
10605 next;
10606 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010607 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10608 next;
10609 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010610 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10611 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010612 "Target"=>get_Signature($AddedVFunc, 2),
10613 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10614 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010615 }
10616 }
10617 }
10618 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010619 if(not checkDump(1, "2.0")
10620 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010621 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010622 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010623 return;
10624 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010625 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010626 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010627 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010628 next if(not $ClassId_Old);
10629 if(not isCreatable($ClassId_Old, 1))
10630 { # skip classes without public constructors (including auto-generated)
10631 # example: class has only a private exported or private inline constructor
10632 next;
10633 }
10634 if($ClassName=~/>/)
10635 { # skip affected template instances
10636 next;
10637 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010638 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010639 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010640 if(not $ClassId_New) {
10641 next;
10642 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010643 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010644 if($Class_New{"Type"}!~/Class|Struct/)
10645 { # became typedef
10646 if($Level eq "Binary") {
10647 next;
10648 }
10649 if($Level eq "Source")
10650 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010651 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010652 if($Class_New{"Type"}!~/Class|Struct/) {
10653 next;
10654 }
10655 $ClassId_New = $Class_New{"Tid"};
10656 }
10657 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010658
10659 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10660 { # incomplete info in the ABI dump
10661 next;
10662 }
10663
10664
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010665 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10666 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 +040010667
10668 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10669 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10670
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010671 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010672 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10673 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010674 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10675 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010676 my $Shift_Old = getShift($ClassId_Old, 1);
10677 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010678 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010679 my ($Added, $Removed) = (0, 0);
10680 my @StableBases_Old = ();
10681 foreach my $BaseId (@Bases_Old)
10682 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010683 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010684 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010685 push(@StableBases_Old, $BaseId);
10686 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010687 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010688 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010689 { # removed base
10690 # excluding namespace::SomeClass to SomeClass renaming
10691 my $ProblemKind = "Removed_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{1}{$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 $Removed+=1;
10734 }
10735 }
10736 my @StableBases_New = ();
10737 foreach my $BaseId (@Bases_New)
10738 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010739 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010740 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010741 push(@StableBases_New, $BaseId);
10742 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010743 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010744 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010745 { # added base
10746 # excluding namespace::SomeClass to SomeClass renaming
10747 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010748 if($Level eq "Binary")
10749 { # Binary-level
10750 if($Shift_Old ne $Shift_New)
10751 { # affected fields
10752 if(havePubFields(\%Class_Old)) {
10753 $ProblemKind .= "_And_Shift";
10754 }
10755 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10756 $ProblemKind .= "_And_Size";
10757 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010758 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010759 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10760 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010761 { # affected v-table
10762 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010763 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010764 }
10765 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010766 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010767 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10768 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010769 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10770 {
10771 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10772 if($ProblemKind=~/VTable/) {
10773 $VTableChanged_M{$SubName}=1;
10774 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010775 }
10776 }
10777 foreach my $Interface (@Affected)
10778 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010779 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10780 next;
10781 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010782 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010783 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010784 "Target"=>$BaseName,
10785 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10786 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10787 "Shift"=>abs($Shift_New-$Shift_Old) );
10788 }
10789 $Added+=1;
10790 }
10791 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010792 if($Level eq "Binary")
10793 { # Binary-level
10794 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010795 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10796 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010797 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010798 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010799 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010800 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010801 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010802 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10803 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010804 if($NewPos!=$OldPos)
10805 { # changed position of the base class
10806 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010807 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010808 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10809 next;
10810 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010811 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10812 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010813 "Target"=>$BaseName,
10814 "Old_Value"=>$OldPos-1,
10815 "New_Value"=>$NewPos-1 );
10816 }
10817 }
10818 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10819 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10820 { # became non-virtual base
10821 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10822 {
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}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10827 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010828 "Target"=>$BaseName );
10829 }
10830 }
10831 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10832 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10833 { # became virtual base
10834 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10835 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010836 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10837 next;
10838 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010839 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10840 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010841 "Target"=>$BaseName );
10842 }
10843 }
10844 }
10845 }
10846 # detect size changes in base classes
10847 if($Shift_Old!=$Shift_New)
10848 { # size of allocable class
10849 foreach my $BaseId (@StableBases_Old)
10850 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010851 my %BaseType = get_Type($BaseId, 1);
10852 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010853 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010854 if($Size_Old ne $Size_New
10855 and $Size_Old and $Size_New)
10856 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010857 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010858 if(isCopyingClass($BaseId, 1)) {
10859 $ProblemType = "Size_Of_Copying_Class";
10860 }
10861 elsif($AllocableClass{1}{$BaseType{"Name"}})
10862 {
10863 if($Size_New>$Size_Old)
10864 { # increased size
10865 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010866 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010867 else
10868 { # decreased size
10869 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10870 if(not havePubFields(\%Class_Old))
10871 { # affected class has no public members
10872 next;
10873 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010874 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010875 }
10876 next if(not $ProblemType);
10877 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10878 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010879 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10880 next;
10881 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010882 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10883 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010884 "Target"=>$BaseType{"Name"},
10885 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10886 "New_Size"=>$Size_New*$BYTE_SIZE );
10887 }
10888 }
10889 }
10890 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010891 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010892 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010893 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010894 { # compare virtual tables size in base classes
10895 my $VShift_Old = getVShift($ClassId_Old, 1);
10896 my $VShift_New = getVShift($ClassId_New, 2);
10897 if($VShift_Old ne $VShift_New)
10898 { # changes in the base class or changes in the list of base classes
10899 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10900 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10901 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010902 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010903 foreach my $BaseId (@AllBases_Old)
10904 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010905 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010906 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010907 { # lost base
10908 next;
10909 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010910 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10911 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010912 if($VSize_Old!=$VSize_New)
10913 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010914 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010915 { # TODO: affected non-virtual methods?
10916 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010917 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10918 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010919 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010920 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010921 { # skip interfaces that have not changed the absolute virtual position
10922 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010923 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010924 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10925 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010926 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010927 $VTableChanged_M{$BaseType{"Name"}} = 1;
10928 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010929 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10930 { # the reason of the layout change: added virtual functions
10931 next if($VirtualReplacement{$VirtFunc});
10932 my $ProblemType = "Added_Virtual_Method";
10933 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10934 $ProblemType = "Added_Pure_Virtual_Method";
10935 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010936 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010937 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010938 "Target"=>get_Signature($VirtFunc, 2) );
10939 }
10940 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
10941 { # the reason of the layout change: removed virtual functions
10942 next if($VirtualReplacement{$VirtFunc});
10943 my $ProblemType = "Removed_Virtual_Method";
10944 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
10945 $ProblemType = "Removed_Pure_Virtual_Method";
10946 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010947 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010948 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010949 "Target"=>get_Signature($VirtFunc, 1) );
10950 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010951 }
10952 }
10953 }
10954 }
10955 }
10956 }
10957 }
10958}
10959
10960sub isCreatable($$)
10961{
10962 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010963 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010964 or isCopyingClass($ClassId, $LibVersion)) {
10965 return 1;
10966 }
10967 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10968 { # Fix for incomplete data: if this class has
10969 # a base class then it should also has a constructor
10970 return 1;
10971 }
10972 if($ReturnedClass{$LibVersion}{$ClassId})
10973 { # returned by some method of this class
10974 # or any other class
10975 return 1;
10976 }
10977 return 0;
10978}
10979
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010980sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010981{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010982 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010983 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
10984 { # parameter of some exported method
10985 return 1;
10986 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010987 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
10988 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010989 { # method from target class
10990 return 1;
10991 }
10992 return 0;
10993}
10994
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010995sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010996{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010997 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010998 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010999 # - virtual
11000 # - pure-virtual
11001 # - non-virtual
11002 if($CompleteSignature{1}{$Interface}{"Data"})
11003 { # global data is not affected
11004 return;
11005 }
11006 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011007 if(not $Class_Id) {
11008 return;
11009 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011010 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011011 if(cmpVTables_Real($CName, 1)==0)
11012 { # no changes
11013 return;
11014 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011015 $CheckedTypes{$Level}{$CName} = 1;
11016 if($Level eq "Binary")
11017 { # Binary-level
11018 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11019 and not isUsedClass($Class_Id, 1, $Level))
11020 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011021 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011022 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011023 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011024 }
11025 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11026 {
11027 if(defined $VirtualTable{2}{$CName}{$Func}
11028 and defined $CompleteSignature{2}{$Func})
11029 {
11030 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11031 and $CompleteSignature{2}{$Func}{"PureVirt"})
11032 { # became pure virtual
11033 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11034 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011035 "Target"=>get_Signature_M($Func, 1) );
11036 $VTableChanged_M{$CName} = 1;
11037 }
11038 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11039 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11040 { # became non-pure virtual
11041 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11042 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011043 "Target"=>get_Signature_M($Func, 1) );
11044 $VTableChanged_M{$CName} = 1;
11045 }
11046 }
11047 }
11048 if($Level eq "Binary")
11049 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011050 # check virtual table structure
11051 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11052 {
11053 next if($Interface eq $AddedVFunc);
11054 next if($VirtualReplacement{$AddedVFunc});
11055 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11056 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11057 { # pure virtual methods affect all others (virtual and non-virtual)
11058 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011059 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011060 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011061 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011062 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011063 elsif(not defined $VirtualTable{1}{$CName}
11064 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011065 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011066 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011067 { # became polymorphous class, added v-table pointer
11068 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011069 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011070 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011071 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011072 }
11073 else
11074 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011075 my $VSize_Old = getVTable_Size($CName, 1);
11076 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011077 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011078 if(isCopyingClass($Class_Id, 1))
11079 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11080 my $ProblemType = "Added_Virtual_Method";
11081 if(isLeafClass($Class_Id, 1)) {
11082 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11083 }
11084 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11085 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011086 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011087 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011088 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011089 else
11090 {
11091 my $ProblemType = "Added_Virtual_Method";
11092 if(isLeafClass($Class_Id, 1)) {
11093 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11094 }
11095 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11096 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011097 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011098 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011099 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011100 }
11101 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011102 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11103 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011104 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011105 if(defined $VirtualTable{1}{$CName}
11106 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011107 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011108 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11109 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011110
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011111 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011112 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011113 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11114 foreach my $ASymbol (@Affected)
11115 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011116 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11117 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011118 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011119 next;
11120 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011121 }
11122 $CheckedSymbols{$Level}{$ASymbol} = 1;
11123 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11124 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011125 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011126 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011127 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011128 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011129 }
11130 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011131 else {
11132 # safe
11133 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011134 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011135 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11136 {
11137 next if($VirtualReplacement{$RemovedVFunc});
11138 if($RemovedVFunc eq $Interface
11139 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11140 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011141 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011142 next;
11143 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011144 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011145 { # became non-polymorphous class, removed v-table pointer
11146 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11147 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011148 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011149 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011150 }
11151 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11152 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11153 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011154 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011155 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011156 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11157 next;
11158 }
11159 my $VPos_New = -1;
11160 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011161 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011162 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11163 }
11164 else
11165 {
11166 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011167 next;
11168 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011169 }
11170 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11171 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11172 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11173 {
11174 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11175 foreach my $ASymbol (@Affected)
11176 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011177 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11178 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011179 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011180 next;
11181 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011182 }
11183 my $ProblemType = "Removed_Virtual_Method";
11184 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11185 $ProblemType = "Removed_Pure_Virtual_Method";
11186 }
11187 $CheckedSymbols{$Level}{$ASymbol} = 1;
11188 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11189 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011190 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011191 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011192 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011193 }
11194 }
11195 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011196 }
11197 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011198 else
11199 { # Source-level
11200 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011201 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011202 next if($Interface eq $AddedVFunc);
11203 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011204 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011205 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11206 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011207 "Target"=>get_Signature($AddedVFunc, 2) );
11208 }
11209 }
11210 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11211 {
11212 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11213 {
11214 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11215 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011216 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011217 }
11218 }
11219 }
11220}
11221
11222sub find_MemberPair_Pos_byName($$)
11223{
11224 my ($Member_Name, $Pair_Type) = @_;
11225 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11226 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11227 {
11228 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11229 {
11230 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11231 $Name=~s/\A[_]+|[_]+\Z//g;
11232 if($Name eq $Member_Name) {
11233 return $MemberPair_Pos;
11234 }
11235 }
11236 }
11237 return "lost";
11238}
11239
11240sub find_MemberPair_Pos_byVal($$)
11241{
11242 my ($Member_Value, $Pair_Type) = @_;
11243 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11244 {
11245 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11246 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11247 return $MemberPair_Pos;
11248 }
11249 }
11250 return "lost";
11251}
11252
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011253sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011254{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011255 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011256 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011257 if( $_->{"T1"} eq $_[0]
11258 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011259 {
11260 return 1;
11261 }
11262 }
11263 return 0;
11264}
11265
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011266sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011267{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011268 my %IDs = (
11269 "T1" => $_[0],
11270 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011271 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011272 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011273}
11274
11275sub isRenamed($$$$$)
11276{
11277 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11278 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11279 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011280 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011281 if(not defined $Type2->{"Memb"}{$MemPos}) {
11282 return "";
11283 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011284 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011285 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011286
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011287 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11288 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011289 if($MemberPair_Pos_Rev eq "lost")
11290 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011291 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11292 { # base type match
11293 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011294 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011295 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11296 { # exact type match
11297 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011298 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011299 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11300 { # size match
11301 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011302 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011303 if(isReserved($Pair_Name))
11304 { # reserved fields
11305 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011306 }
11307 }
11308 return "";
11309}
11310
11311sub isLastElem($$)
11312{
11313 my ($Pos, $TypeRef) = @_;
11314 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11315 if($Name=~/last|count|max|total/i)
11316 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11317 return 1;
11318 }
11319 elsif($Name=~/END|NLIMITS\Z/)
11320 { # __RLIMIT_NLIMITS
11321 return 1;
11322 }
11323 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11324 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11325 { # NImageFormats, NColorRoles
11326 return 1;
11327 }
11328 return 0;
11329}
11330
11331sub nonComparable($$)
11332{
11333 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011334
11335 my $N1 = $T1->{"Name"};
11336 my $N2 = $T2->{"Name"};
11337
11338 $N1=~s/\A(struct|union|enum) //;
11339 $N2=~s/\A(struct|union|enum) //;
11340
11341 if($N1 ne $N2
11342 and not isAnon($N1)
11343 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011344 { # different names
11345 if($T1->{"Type"} ne "Pointer"
11346 or $T2->{"Type"} ne "Pointer")
11347 { # compare base types
11348 return 1;
11349 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011350 if($N1!~/\Avoid\s*\*/
11351 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011352 {
11353 return 1;
11354 }
11355 }
11356 elsif($T1->{"Type"} ne $T2->{"Type"})
11357 { # different types
11358 if($T1->{"Type"} eq "Class"
11359 and $T2->{"Type"} eq "Struct")
11360 { # "class" to "struct"
11361 return 0;
11362 }
11363 elsif($T2->{"Type"} eq "Class"
11364 and $T1->{"Type"} eq "Struct")
11365 { # "struct" to "class"
11366 return 0;
11367 }
11368 else
11369 { # "class" to "enum"
11370 # "union" to "class"
11371 # ...
11372 return 1;
11373 }
11374 }
11375 return 0;
11376}
11377
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011378sub isOpaque($)
11379{
11380 my $T = $_[0];
11381 if(not defined $T->{"Memb"})
11382 {
11383 return 1;
11384 }
11385 return 0;
11386}
11387
11388sub removeVPtr($)
11389{ # support for old ABI dumps
11390 my $TPtr = $_[0];
11391 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11392 if($#Pos>=1)
11393 {
11394 foreach my $Pos (0 .. $#Pos-1)
11395 {
11396 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11397 }
11398 delete($TPtr->{"Memb"}{$#Pos});
11399 }
11400}
11401
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011402sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011403{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011404 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011405 return {} if(not $Type1_Id or not $Type2_Id);
11406
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011407 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011408 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011409 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011410 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011411
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011412 my %Type1 = get_Type($Type1_Id, 1);
11413 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011414 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011415 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011416 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011417
11418 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011419 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11420 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011421
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011422 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11423
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011424 my %SubProblems = ();
11425
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011426 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11427 {
11428 if($Type1_Pure{"Type"}=~/Struct|Union/
11429 and $Type2_Pure{"Type"}=~/Struct|Union/)
11430 {
11431 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11432 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011433 if(not defined $UsedDump{1}{"DWARF"}
11434 and not defined $UsedDump{2}{"DWARF"})
11435 {
11436 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11437 "Target"=>$Type1_Pure{"Name"},
11438 "Type_Name"=>$Type1_Pure{"Name"} );
11439 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011440
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011441 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011442 }
11443 }
11444 }
11445
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011446 if(not $Type1_Pure{"Size"}
11447 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011448 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011449 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11450 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11451 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011452 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011453 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011454 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011455 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011456 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011457 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011458 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011459 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11460 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11461 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011462
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011463 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11464 return {};
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011465 }
11466
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011467 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11468 { # support for old ABI dumps
11469 # _vptr field added in 3.0
11470 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11471 {
11472 if(defined $Type2_Pure{"Memb"}
11473 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11474 {
11475 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11476 delete($Type2_Pure{"Memb"}{0});
11477 }
11478 else {
11479 removeVPtr(\%Type2_Pure);
11480 }
11481 }
11482 }
11483 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11484 {
11485 if(defined $Type1_Pure{"Memb"}
11486 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11487 {
11488 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11489 delete($Type1_Pure{"Memb"}{0});
11490 }
11491 else {
11492 removeVPtr(\%Type1_Pure);
11493 }
11494 }
11495 }
11496 }
11497
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011498 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11499 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011500
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011501 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011502 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11503 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011504 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011505 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11506 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011507 if($Base_1{"Name"} ne $Base_2{"Name"})
11508 {
11509 if(differentDumps("G")
11510 or differentDumps("V"))
11511 { # different GCC versions or different dumps
11512 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11513 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11514 # std::__va_list and __va_list
11515 $Base_1{"Name"}=~s/\A(\w+::)+//;
11516 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011517 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11518 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011519 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011520 }
11521 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11522 and $Base_1{"Name"} ne $Base_2{"Name"})
11523 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011524 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011525 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011526 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011527 {
11528 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11529 "Target"=>$Typedef_1{"Name"},
11530 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011531 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11532 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11533 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011534 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11535 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011536 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011537 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011538 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11539 {
11540 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11541 "Target"=>$Typedef_1{"Name"},
11542 "Type_Name"=>$Typedef_1{"Name"},
11543 "Old_Value"=>$Base_1{"Name"},
11544 "New_Value"=>$Base_2{"Name"} );
11545 }
11546 else
11547 {
11548 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11549 "Target"=>$Typedef_1{"Name"},
11550 "Type_Name"=>$Typedef_1{"Name"},
11551 "Old_Value"=>$Base_1{"Name"},
11552 "New_Value"=>$Base_2{"Name"} );
11553 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011554 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011555 }
11556 }
11557 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11558 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011559 my $TT1 = $Type1_Pure{"Type"};
11560 my $TT2 = $Type2_Pure{"Type"};
11561
11562 if($TT1 ne $TT2
11563 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011564 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011565 my $Short1 = $Type1_Pure{"Name"};
11566 my $Short2 = $Type2_Pure{"Name"};
11567
11568 $Short1=~s/\A\Q$TT1\E //ig;
11569 $Short2=~s/\A\Q$TT2\E //ig;
11570
11571 if($Short1 eq $Short2)
11572 {
11573 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11574 "Target"=>$Type1_Pure{"Name"},
11575 "Type_Name"=>$Type1_Pure{"Name"},
11576 "Old_Value"=>lc($Type1_Pure{"Type"}),
11577 "New_Value"=>lc($Type2_Pure{"Type"}) );
11578 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011579 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011580 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011581 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011582 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011583 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11584 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11585 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11586 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011587 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011588 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011589 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011590 {
11591 my $ProblemKind = "DataType_Size";
11592 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011593 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011594 {
11595 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11596 $ProblemKind = "Size_Of_Copying_Class";
11597 }
11598 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11599 {
11600 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11601 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11602 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011603 else
11604 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011605 # descreased size of allocable class
11606 # it has no special effects
11607 }
11608 }
11609 }
11610 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11611 "Target"=>$Type1_Pure{"Name"},
11612 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011613 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011614 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011615 }
11616 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011617 if(defined $Type1_Pure{"BaseType"}
11618 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011619 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011620 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11621 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011622 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011623 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11624 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011625 }
11626 }
11627 }
11628 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11629 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11630 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11631 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11632 { # detect removed and renamed fields
11633 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11634 next if(not $Member_Name);
11635 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);
11636 if($MemberPair_Pos eq "lost")
11637 {
11638 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11639 {
11640 if(isUnnamed($Member_Name))
11641 { # support for old-version dumps
11642 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011643 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011644 next;
11645 }
11646 }
11647 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11648 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011649 $RenamedField{$Member_Pos} = $RenamedTo;
11650 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011651 }
11652 else
11653 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011654 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011655 }
11656 }
11657 elsif($Type1_Pure{"Type"} eq "Enum")
11658 {
11659 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11660 next if($Member_Value1 eq "");
11661 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11662 if($MemberPair_Pos ne "lost")
11663 { # renamed
11664 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11665 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11666 if($MemberPair_Pos_Rev eq "lost")
11667 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011668 $RenamedField{$Member_Pos} = $RenamedTo;
11669 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011670 }
11671 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011672 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011673 }
11674 }
11675 else
11676 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011677 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011678 }
11679 }
11680 }
11681 else
11682 { # related
11683 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11684 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11685 }
11686 }
11687 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11688 { # detect added fields
11689 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11690 next if(not $Member_Name);
11691 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);
11692 if($MemberPair_Pos eq "lost")
11693 {
11694 if(isUnnamed($Member_Name))
11695 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011696 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011697 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011698 next;
11699 }
11700 }
11701 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11702 {
11703 if(not $RenamedField_Rev{$Member_Pos})
11704 { # added
11705 $AddedField{$Member_Pos}=1;
11706 }
11707 }
11708 }
11709 }
11710 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11711 { # detect moved fields
11712 my (%RelPos, %RelPosName, %AbsPos) = ();
11713 my $Pos = 0;
11714 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11715 { # relative positions in 1st version
11716 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11717 next if(not $Member_Name);
11718 if(not $RemovedField{$Member_Pos})
11719 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011720 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011721 $RelPosName{1}{$Pos} = $Member_Name;
11722 $AbsPos{1}{$Pos++} = $Member_Pos;
11723 }
11724 }
11725 $Pos = 0;
11726 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11727 { # relative positions in 2nd version
11728 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11729 next if(not $Member_Name);
11730 if(not $AddedField{$Member_Pos})
11731 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011732 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011733 $RelPosName{2}{$Pos} = $Member_Name;
11734 $AbsPos{2}{$Pos++} = $Member_Pos;
11735 }
11736 }
11737 foreach my $Member_Name (keys(%{$RelPos{1}}))
11738 {
11739 my $RPos1 = $RelPos{1}{$Member_Name};
11740 my $AbsPos1 = $NameToPosA{$Member_Name};
11741 my $Member_Name2 = $Member_Name;
11742 if(my $RenamedTo = $RenamedField{$AbsPos1})
11743 { # renamed
11744 $Member_Name2 = $RenamedTo;
11745 }
11746 my $RPos2 = $RelPos{2}{$Member_Name2};
11747 if($RPos2 ne "" and $RPos1 ne $RPos2)
11748 { # different relative positions
11749 my $AbsPos2 = $NameToPosB{$Member_Name2};
11750 if($AbsPos1 ne $AbsPos2)
11751 { # different absolute positions
11752 my $ProblemType = "Moved_Field";
11753 if(not isPublic(\%Type1_Pure, $AbsPos1))
11754 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011755 if($Level eq "Source") {
11756 next;
11757 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011758 $ProblemType = "Moved_Private_Field";
11759 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011760 if($Level eq "Binary"
11761 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011762 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011763 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011764 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011765 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011766 if($MemSize1 ne $MemSize2) {
11767 $ProblemType .= "_And_Size";
11768 }
11769 }
11770 if($ProblemType eq "Moved_Private_Field") {
11771 next;
11772 }
11773 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11774 "Target"=>$Member_Name,
11775 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011776 "Old_Value"=>$RPos1,
11777 "New_Value"=>$RPos2 );
11778 }
11779 }
11780 }
11781 }
11782 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011783 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011784 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11785 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011786 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011787 if(my $RenamedTo = $RenamedField{$Member_Pos})
11788 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011789 if(defined $Constants{2}{$Member_Name})
11790 {
11791 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11792 { # define OLD NEW
11793 next; # Safe
11794 }
11795 }
11796
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011797 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11798 {
11799 if(isPublic(\%Type1_Pure, $Member_Pos))
11800 {
11801 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11802 "Target"=>$Member_Name,
11803 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011804 "Old_Value"=>$Member_Name,
11805 "New_Value"=>$RenamedTo );
11806 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011807 elsif(isReserved($Member_Name))
11808 {
11809 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11810 "Target"=>$Member_Name,
11811 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011812 "Old_Value"=>$Member_Name,
11813 "New_Value"=>$RenamedTo );
11814 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011815 }
11816 elsif($Type1_Pure{"Type"} eq "Enum")
11817 {
11818 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11819 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11820 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011821 "Old_Value"=>$Member_Name,
11822 "New_Value"=>$RenamedTo );
11823 }
11824 }
11825 elsif($RemovedField{$Member_Pos})
11826 { # removed
11827 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11828 {
11829 my $ProblemType = "Removed_Field";
11830 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011831 or isUnnamed($Member_Name))
11832 {
11833 if($Level eq "Source") {
11834 next;
11835 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011836 $ProblemType = "Removed_Private_Field";
11837 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011838 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011839 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011840 {
11841 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11842 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011843 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 +040011844 { # changed offset
11845 $ProblemType .= "_And_Layout";
11846 }
11847 }
11848 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11849 { # affected size
11850 $ProblemType .= "_And_Size";
11851 }
11852 }
11853 if($ProblemType eq "Removed_Private_Field") {
11854 next;
11855 }
11856 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11857 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011858 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011859 }
11860 elsif($Type2_Pure{"Type"} eq "Union")
11861 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011862 if($Level eq "Binary"
11863 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011864 {
11865 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11866 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011867 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011868 }
11869 else
11870 {
11871 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11872 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011873 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011874 }
11875 }
11876 elsif($Type1_Pure{"Type"} eq "Enum")
11877 {
11878 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11879 "Target"=>$Member_Name,
11880 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011881 "Old_Value"=>$Member_Name );
11882 }
11883 }
11884 else
11885 { # changed
11886 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11887 if($Type1_Pure{"Type"} eq "Enum")
11888 {
11889 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11890 next if($Member_Value1 eq "");
11891 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11892 next if($Member_Value2 eq "");
11893 if($Member_Value1 ne $Member_Value2)
11894 {
11895 my $ProblemType = "Enum_Member_Value";
11896 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11897 $ProblemType = "Enum_Last_Member_Value";
11898 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011899 if($SkipConstants{1}{$Member_Name}) {
11900 $ProblemType = "Enum_Private_Member_Value";
11901 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011902 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11903 "Target"=>$Member_Name,
11904 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011905 "Old_Value"=>$Member_Value1,
11906 "New_Value"=>$Member_Value2 );
11907 }
11908 }
11909 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11910 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011911 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
11912 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
11913
11914 if($Access1 ne "private"
11915 and $Access2 eq "private")
11916 {
11917 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
11918 "Target"=>$Member_Name,
11919 "Type_Name"=>$Type1_Pure{"Name"});
11920 }
11921 elsif($Access1 ne "protected"
11922 and $Access1 ne "private"
11923 and $Access2 eq "protected")
11924 {
11925 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
11926 "Target"=>$Member_Name,
11927 "Type_Name"=>$Type1_Pure{"Name"});
11928 }
11929
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011930 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
11931 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011932 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011933 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
11934 $SizeV1 = $BSize1;
11935 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011936 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011937 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
11938 $SizeV2 = $BSize2;
11939 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011940 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
11941 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011942 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011943 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011944 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011945 {
11946 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
11947 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
11948 { # field size change (including anon-structures and unions)
11949 # - same types
11950 # - unnamed types
11951 # - bitfields
11952 my $ProblemType = "Field_Size";
11953 if(not isPublic(\%Type1_Pure, $Member_Pos)
11954 or isUnnamed($Member_Name))
11955 { # should not be accessed by applications, goes to "Low Severity"
11956 # example: "abidata" members in GStreamer types
11957 $ProblemType = "Private_".$ProblemType;
11958 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011959 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 +040011960 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011961 if($Type2_Pure{"Type"} ne "Union"
11962 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011963 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011964 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 +040011965 { # changed offset
11966 $ProblemType .= "_And_Layout";
11967 }
11968 }
11969 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11970 $ProblemType .= "_And_Type_Size";
11971 }
11972 }
11973 if($ProblemType eq "Private_Field_Size")
11974 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011975 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040011976 if($ProblemType eq "Field_Size")
11977 {
11978 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
11979 { # Low severity
11980 $ProblemType = "Struct_Field_Size_Increased";
11981 }
11982 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011983 if($ProblemType)
11984 { # register a problem
11985 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11986 "Target"=>$Member_Name,
11987 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011988 "Old_Size"=>$SizeV1,
11989 "New_Size"=>$SizeV2);
11990 }
11991 }
11992 }
11993 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
11994 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
11995 { # do NOT check bitfield type changes
11996 next;
11997 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011998 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011999 {
12000 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12001 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12002 {
12003 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12004 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012005 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012006 }
12007 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12008 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12009 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012010 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012011 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012012 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012013 }
12014 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012015 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12016 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012017 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012018 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12019 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012020
12021 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012022 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012023 or $ProblemType eq "Field_Type_And_Size"
12024 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012025 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012026 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012027 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012028 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012029 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012030 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012031 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012032 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012033 }
12034 }
12035 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12036 {
12037 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012038 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012039 }
12040 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012041 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012042 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012043 }
12044 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12045 {
12046 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012047 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012048 }
12049 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012050 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012051 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012052 }
12053 }
12054 }
12055
12056 if($Level eq "Source")
12057 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012058 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012059 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012060 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12061 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012062
12063 if($ProblemType eq "Field_Type")
12064 {
12065 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012066 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012067 }
12068 }
12069 }
12070 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012071
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012072 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012073 {
12074 my $ProblemType_Init = $ProblemType;
12075 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012076 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012077 if(not isPublic(\%Type1_Pure, $Member_Pos)
12078 or isUnnamed($Member_Name)) {
12079 $ProblemType = "Private_".$ProblemType;
12080 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012081 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 +040012082 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012083 if($Type2_Pure{"Type"} ne "Union"
12084 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012085 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012086 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 +040012087 { # changed offset
12088 $ProblemType .= "_And_Layout";
12089 }
12090 }
12091 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12092 $ProblemType .= "_And_Type_Size";
12093 }
12094 }
12095 }
12096 else
12097 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012098 # TODO: Private_Field_Type rule?
12099
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012100 if(not isPublic(\%Type1_Pure, $Member_Pos)
12101 or isUnnamed($Member_Name)) {
12102 next;
12103 }
12104 }
12105 if($ProblemType eq "Private_Field_Type_And_Size")
12106 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012107 }
12108 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12109 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012110 "Type_Name"=>$Type1_Pure{"Name"});
12111
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012112 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012113 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012114 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012115 }
12116 }
12117 if(not isPublic(\%Type1_Pure, $Member_Pos))
12118 { # do NOT check internal type changes
12119 next;
12120 }
12121 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012122 { # checking member type changes
12123 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12124
12125 my %DupProblems = ();
12126
12127 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012128 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012129 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012130 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012131 if(not defined $AllAffected)
12132 {
12133 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12134 next;
12135 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012136 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012137
12138 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12139 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12140
12141 if(not defined $AllAffected)
12142 {
12143 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012144 }
12145 }
12146 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012147
12148 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012149 }
12150 }
12151 }
12152 }
12153 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12154 { # checking added members, public and private
12155 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12156 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012157 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012158 if($AddedField{$Member_Pos})
12159 { # added
12160 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12161 {
12162 my $ProblemType = "Added_Field";
12163 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012164 or isUnnamed($Member_Name))
12165 {
12166 if($Level eq "Source") {
12167 next;
12168 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012169 $ProblemType = "Added_Private_Field";
12170 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012171 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012172 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012173 {
12174 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12175 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012176 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 +040012177 { # changed offset
12178 $ProblemType .= "_And_Layout";
12179 }
12180 }
12181 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12182 $ProblemType .= "_And_Size";
12183 }
12184 }
12185 if($ProblemType eq "Added_Private_Field")
12186 { # skip added private fields
12187 next;
12188 }
12189 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12190 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012191 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012192 }
12193 elsif($Type2_Pure{"Type"} eq "Union")
12194 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012195 if($Level eq "Binary"
12196 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012197 {
12198 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12199 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012200 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012201 }
12202 else
12203 {
12204 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12205 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012206 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012207 }
12208 }
12209 elsif($Type2_Pure{"Type"} eq "Enum")
12210 {
12211 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12212 next if($Member_Value eq "");
12213 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12214 "Target"=>$Member_Name,
12215 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012216 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012217 }
12218 }
12219 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012220
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012221 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012222 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012223}
12224
12225sub isUnnamed($) {
12226 return $_[0]=~/\Aunnamed\d+\Z/;
12227}
12228
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012229sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012230{
12231 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012232 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12233 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12234 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12235 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012236 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012237 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012238 }
12239 return $TypeName;
12240}
12241
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012242sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012243{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012244 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012245 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012246 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12247 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012248 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012249 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12250 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012251 return () if(not $Type{"Type"});
12252 if($Type{"Type"} ne $Type_Type)
12253 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012254 return () if(not $Type{"BaseType"});
12255 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012256 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012257 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012258 return %Type;
12259}
12260
12261my %TypeSpecAttributes = (
12262 "Const" => 1,
12263 "Volatile" => 1,
12264 "ConstVolatile" => 1,
12265 "Restrict" => 1,
12266 "Typedef" => 1
12267);
12268
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012269sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012270{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012271 my ($TypeId, $Info) = @_;
12272 if(not $TypeId or not $Info
12273 or not $Info->{$TypeId}) {
12274 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012275 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012276 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12277 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12278 }
12279 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012280 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012281 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012282 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012283 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012284 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012285 return %Type;
12286}
12287
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012288sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012289{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012290 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012291 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012292 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12293 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012294 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012295 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12296 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012297 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12298 my $PLevel = 0;
12299 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12300 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012301 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012302 return $PLevel if(not $Type{"BaseType"});
12303 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12304 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12305 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012306}
12307
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012308sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012309{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012310 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012311 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012312 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12313 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012314 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012315 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12316 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012317 return %Type if(not $Type{"BaseType"});
12318 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012319 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012320 return %Type;
12321}
12322
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012323sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012324{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012325 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012326 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012327 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12328 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012329 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012330 my $Qual = "";
12331 if($Type{"Type"} eq "Pointer") {
12332 $Qual .= "*";
12333 }
12334 elsif($Type{"Type"} eq "Ref") {
12335 $Qual .= "&";
12336 }
12337 elsif($Type{"Type"} eq "ConstVolatile") {
12338 $Qual .= "const volatile";
12339 }
12340 elsif($Type{"Type"} eq "Const"
12341 or $Type{"Type"} eq "Volatile"
12342 or $Type{"Type"} eq "Restrict") {
12343 $Qual .= lc($Type{"Type"});
12344 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012345 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012346 return $BQual.$Qual;
12347}
12348
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012349sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012350{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012351 my ($TypeId, $Info) = @_;
12352 if(not $TypeId or not $Info
12353 or not $Info->{$TypeId}) {
12354 return ();
12355 }
12356 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012357 return %Type if(not $Type{"BaseType"});
12358 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012359 {
12360 if($Info->{$BTid}) {
12361 return %{$Info->{$BTid}};
12362 }
12363 else { # something is going wrong
12364 return ();
12365 }
12366 }
12367 else {
12368 return %Type;
12369 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012370}
12371
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012372sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012373{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012374 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012375 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012376 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12377 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012378}
12379
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012380sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012381{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012382 my $Symbol = $_[0];
12383 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12384}
12385
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012386sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012387 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12388}
12389
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012390sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012391{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012392 my ($SInfo, $LibVersion) = @_;
12393
12394 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012395 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012396 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012397 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012398 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012399 return 1;
12400 }
12401 }
12402 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012403 if(my $ShortName = $SInfo->{"ShortName"})
12404 {
12405 if(index($ShortName,"<")!=-1
12406 and index($ShortName,">")!=-1) {
12407 return 1;
12408 }
12409 }
12410
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012411 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012412}
12413
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012414sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012415{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012416 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012417 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012418 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012419 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012420 { # class specialization
12421 return 1;
12422 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012423 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012424 { # method specialization
12425 return 1;
12426 }
12427 }
12428 return 0;
12429}
12430
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012431sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012432{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012433 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012434
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012435 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012436 { # non-public global data
12437 return 0;
12438 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012439
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012440 if(defined $SkipInternalSymbols)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012441 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012442 return 0 if($Symbol=~/($SkipInternalSymbols)/);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012443 }
12444
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012445 if($Symbol=~/\A_Z/)
12446 {
12447 if($Symbol=~/[CD][3-4]E/) {
12448 return 0;
12449 }
12450 }
12451
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012452 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012453 { # support for old ABI dumps in --headers-only mode
12454 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12455 {
12456 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12457 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012458 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012459 if(not $PType or $PType eq "Unknown") {
12460 return 0;
12461 }
12462 }
12463 }
12464 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012465 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012466 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012467 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12468
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012469 if($SkipSymbols{$LibVersion}{$Symbol})
12470 { # user defined symbols to ignore
12471 return 0;
12472 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012473
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012474 if($SymbolsListPath and not $SymbolsList{$Symbol})
12475 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012476 if(not $TargetHeadersPath or not $Header
12477 or not is_target_header($Header, 1))
12478 { # -symbols-list | -headers-list
12479 return 0;
12480 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012481 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012482
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012483 if($AppPath and not $SymbolsList_App{$Symbol})
12484 { # user defined symbols (in application)
12485 return 0;
12486 }
12487
12488 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12489
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012490 if($ClassId)
12491 {
12492 if(not isTargetType($ClassId, $LibVersion)) {
12493 return 0;
12494 }
12495 }
12496
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012497 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12498 if(not $NameSpace and $ClassId)
12499 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012500 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012501 }
12502 if($NameSpace)
12503 { # user defined namespaces to ignore
12504 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12505 return 0;
12506 }
12507 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12508 { # nested namespaces
12509 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12510 return 0;
12511 }
12512 }
12513 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012514 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012515 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012516 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012517 { # --skip-headers or <skip_headers> (not <skip_including>)
12518 if($Skip==1) {
12519 return 0;
12520 }
12521 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012522 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012523 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012524 { # user defined types
12525 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12526
12527 if(not $TypesList{$CName})
12528 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012529 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12530 {
12531 $CName=~s/\A\Q$NS\E\:\://g;
12532 }
12533
12534 if(not $TypesList{$CName})
12535 {
12536 my $Found = 0;
12537
12538 while($CName=~s/\:\:.+?\Z//)
12539 {
12540 if($TypesList{$CName})
12541 {
12542 $Found = 1;
12543 last;
12544 }
12545 }
12546
12547 if(not $Found) {
12548 return 0;
12549 }
12550 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012551 }
12552 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012553
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012554 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12555 { # non-target symbols
12556 return 0;
12557 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012558 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012559 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012560 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12561 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012562 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012563 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12564 { # inline virtual methods
12565 if($Type=~/InlineVirt/) {
12566 return 1;
12567 }
12568 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12569 if(not $Allocable)
12570 { # check bases
12571 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12572 {
12573 if(not isCopyingClass($DCId, $LibVersion))
12574 { # exists a derived class without default c-tor
12575 $Allocable=1;
12576 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012577 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012578 }
12579 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012580 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012581 return 0;
12582 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012583 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012584 else
12585 { # inline non-virtual methods
12586 return 0;
12587 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012588 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012589 }
12590 }
12591 return 1;
12592}
12593
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012594sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012595{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012596 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012597 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12598 {
12599 if(link_symbol($Symbol, 1, "+Deps"))
12600 { # linker can find a new symbol
12601 # in the old-version library
12602 # So, it's not a new symbol
12603 next;
12604 }
12605 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012606 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012607 next;
12608 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012609 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012610 }
12611}
12612
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012613sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012614{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012615 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012616 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12617 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012618 if(link_symbol($Symbol, 2, "+Deps"))
12619 { # linker can find an old symbol
12620 # in the new-version library
12621 next;
12622 }
12623 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012624 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012625 next;
12626 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012627 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012628 }
12629}
12630
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012631sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012632{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012633 my $Level = $_[0];
12634 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012635 { # checking added symbols
12636 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012637 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012638 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012639 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012640 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012641 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012642 { # checking removed symbols
12643 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012644 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012645 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012646 { # skip v-tables for templates, that should not be imported by applications
12647 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012648 if(my $CName = $VTableClass{$Symbol})
12649 {
12650 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12651 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012652 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012653 next;
12654 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012655 }
12656 }
12657 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012658 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012659 }
12660 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12661 { # symbols for pure virtual methods cannot be called by clients
12662 next;
12663 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012664 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012665 }
12666}
12667
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012668sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012669{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012670 my ($LibVersion, $V) = @_;
12671 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12672 return $Cache{"checkDump"}{$LibVersion}{$V};
12673 }
12674 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012675}
12676
12677sub detectAdded_H($)
12678{
12679 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012680 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12681 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012682 if($Level eq "Source")
12683 { # remove symbol version
12684 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12685 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012686
12687 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12688 { # skip artificial constructors
12689 next;
12690 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012691 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012692 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12693 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012694 next;
12695 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012696 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012697 next;
12698 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012699 if(not defined $CompleteSignature{1}{$Symbol}
12700 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12701 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012702 if($UsedDump{2}{"SrcBin"})
12703 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012704 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012705 { # support for old and different (!) ABI dumps
12706 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12707 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012708 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012709 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012710 {
12711 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12712 {
12713 if($Lang eq "C")
12714 { # support for old ABI dumps: missed extern "C" functions
12715 next;
12716 }
12717 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012718 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012719 else
12720 {
12721 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012722 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012723 next;
12724 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012725 }
12726 }
12727 }
12728 }
12729 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012730 }
12731 }
12732}
12733
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012734sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012735{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012736 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012737 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12738 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012739 if($Level eq "Source")
12740 { # remove symbol version
12741 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12742 $Symbol=$SN;
12743 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012744 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12745 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012746 next;
12747 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012748 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012749 next;
12750 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012751 if(not defined $CompleteSignature{2}{$Symbol}
12752 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012753 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012754 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012755 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012756 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012757 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012758 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12759 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012760 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012761 if($CheckHeadersOnly)
12762 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012763 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12764 {
12765 if($Lang eq "C")
12766 { # support for old ABI dumps: missed extern "C" functions
12767 next;
12768 }
12769 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012770 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012771 else
12772 {
12773 if(not link_symbol($Symbol, 1, "-Deps"))
12774 { # skip removed inline symbols
12775 next;
12776 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012777 }
12778 }
12779 }
12780 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012781 if(not checkDump(1, "2.15"))
12782 {
12783 if($Symbol=~/_IT_E\Z/)
12784 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12785 next;
12786 }
12787 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012788 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12789 {
12790 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12791 {
12792 if(defined $Constants{2}{$Short})
12793 {
12794 my $Val = $Constants{2}{$Short}{"Value"};
12795 if(defined $Func_ShortName{2}{$Val})
12796 { # old name defined to new
12797 next;
12798 }
12799 }
12800 }
12801
12802 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012803 $RemovedInt{$Level}{$Symbol} = 1;
12804 if($Level eq "Source")
12805 { # search for a source-compatible equivalent
12806 setAlternative($Symbol, $Level);
12807 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012808 }
12809 }
12810}
12811
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012812sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012813{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012814 my $Level = $_[0];
12815 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012816 { # checking added symbols
12817 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012818 next if($CompleteSignature{2}{$Symbol}{"Private"});
12819 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012820 if($Level eq "Binary")
12821 {
12822 if($CompleteSignature{2}{$Symbol}{"InLine"})
12823 {
12824 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12825 { # skip inline non-virtual functions
12826 next;
12827 }
12828 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012829 }
12830 else
12831 { # Source
12832 if($SourceAlternative_B{$Symbol}) {
12833 next;
12834 }
12835 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012836 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012837 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012838 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012839 { # checking removed symbols
12840 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012841 next if($CompleteSignature{1}{$Symbol}{"Private"});
12842 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012843 if($Level eq "Binary")
12844 {
12845 if($CompleteSignature{1}{$Symbol}{"InLine"})
12846 {
12847 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
12848 { # skip inline non-virtual functions
12849 next;
12850 }
12851 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012852 }
12853 else
12854 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012855 if(my $Alt = $SourceAlternative{$Symbol})
12856 {
12857 if(defined $CompleteSignature{1}{$Alt}
12858 and $CompleteSignature{1}{$Symbol}{"Const"})
12859 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012860 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012861 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012862 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012863 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012864 }
12865 else
12866 { # do NOT show removed symbol
12867 next;
12868 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012869 }
12870 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012871 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012872 }
12873}
12874
12875sub addParamNames($)
12876{
12877 my $LibraryVersion = $_[0];
12878 return if(not keys(%AddIntParams));
12879 my $SecondVersion = $LibraryVersion==1?2:1;
12880 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
12881 {
12882 next if(not keys(%{$AddIntParams{$Interface}}));
12883 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012884 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012885 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
12886 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012887 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012888 if(defined $CompleteSignature{$SecondVersion}{$Interface}
12889 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
12890 {
12891 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
12892 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12893 }
12894 }
12895 else {
12896 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12897 }
12898 }
12899 }
12900 }
12901}
12902
12903sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012904{ # detect changed typedefs to show
12905 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012906 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
12907 {
12908 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012909 my $BName1 = $Typedef_BaseName{1}{$Typedef};
12910 if(not $BName1 or isAnon($BName1)) {
12911 next;
12912 }
12913 my $BName2 = $Typedef_BaseName{2}{$Typedef};
12914 if(not $BName2 or isAnon($BName2)) {
12915 next;
12916 }
12917 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012918 $ChangedTypedef{$Typedef} = 1;
12919 }
12920 }
12921}
12922
12923sub get_symbol_suffix($$)
12924{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012925 my ($Symbol, $Full) = @_;
12926 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040012927 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012928 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012929 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012930 if(not $Full) {
12931 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
12932 }
12933 return $Suffix;
12934}
12935
12936sub get_symbol_prefix($$)
12937{
12938 my ($Symbol, $LibVersion) = @_;
12939 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
12940 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12941 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012942 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012943 }
12944 return $ShortName;
12945}
12946
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012947sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012948{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012949 my $Symbol = $_[0];
12950 my $PSymbol = $Symbol;
12951 if(not defined $CompleteSignature{2}{$PSymbol}
12952 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
12953 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
12954 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012955 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012956 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012957 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012958 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012959 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
12960 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012961 {
12962 if(defined $CompleteSignature{2}{$PSymbol}
12963 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12964 {
12965 $SourceAlternative{$Symbol} = $PSymbol;
12966 $SourceAlternative_B{$PSymbol} = $Symbol;
12967 if(not defined $CompleteSignature{1}{$PSymbol}
12968 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12969 $SourceReplacement{$Symbol} = $PSymbol;
12970 }
12971 }
12972 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012973 }
12974 else
12975 {
12976 foreach my $Sp ("KV", "VK", "K", "V")
12977 {
12978 if($PSymbol=~s/\A_ZN$Sp/_ZN/
12979 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
12980 {
12981 if(defined $CompleteSignature{2}{$PSymbol}
12982 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12983 {
12984 $SourceAlternative{$Symbol} = $PSymbol;
12985 $SourceAlternative_B{$PSymbol} = $Symbol;
12986 if(not defined $CompleteSignature{1}{$PSymbol}
12987 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12988 $SourceReplacement{$Symbol} = $PSymbol;
12989 }
12990 }
12991 }
12992 $PSymbol = $Symbol;
12993 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012994 }
12995 }
12996 }
12997 return "";
12998}
12999
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013000sub getSymKind($$)
13001{
13002 my ($Symbol, $LibVersion) = @_;
13003 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13004 {
13005 return "Global_Data";
13006 }
13007 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13008 {
13009 return "Method";
13010 }
13011 return "Function";
13012}
13013
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013014sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013015{
13016 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013017 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013018
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013019 mergeBases($Level);
13020
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013021 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013022 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013023 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013024 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013025 next;
13026 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013027 if(defined $CompleteSignature{1}{$Symbol}
13028 and $CompleteSignature{1}{$Symbol}{"Header"})
13029 { # double-check added symbol
13030 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013031 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013032 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013033 next;
13034 }
13035 if($Symbol=~/\A(_Z|\?)/)
13036 { # C++
13037 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13038 }
13039 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13040 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013041 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13042 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013043 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013044 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013045 {
13046 if($TName_Tid{1}{$AffectedClass_Name})
13047 { # class should exist in previous version
13048 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13049 { # old v-table is NOT copied by old applications
13050 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13051 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013052 "Target"=>get_Signature($Symbol, 2),
13053 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013054 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013055 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013056 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013057 }
13058 }
13059 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013060 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13061 { # check all removed exported symbols
13062 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013063 next;
13064 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013065 if(defined $CompleteSignature{2}{$Symbol}
13066 and $CompleteSignature{2}{$Symbol}{"Header"})
13067 { # double-check removed symbol
13068 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013069 }
13070 if($CompleteSignature{1}{$Symbol}{"Private"})
13071 { # skip private methods
13072 next;
13073 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013074 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013075 next;
13076 }
13077 $CheckedSymbols{$Level}{$Symbol} = 1;
13078 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13079 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013080 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13081 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013082 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013083 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13084 {
13085 if($TName_Tid{2}{$AffectedClass_Name})
13086 { # class should exist in newer version
13087 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13088 { # old v-table is NOT copied by old applications
13089 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13090 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013091 "Target"=>get_Signature($OverriddenMethod, 1),
13092 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013093 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013094 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013095 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013096 }
13097 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013098 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013099 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013100 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013101 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013102 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013103 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013104 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013105 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013106 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013107 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013108 {
13109 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13110 "Target"=>$tr_name{$Symbol},
13111 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013112 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013113 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013114 else
13115 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013116 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013117 "Target"=>$tr_name{$Symbol},
13118 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013119 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013120 }
13121 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013122 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013123 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013124 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013125 {
13126 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13127 "Target"=>$tr_name{$Symbol},
13128 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013129 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013130 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013131 else
13132 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013133 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013134 "Target"=>$tr_name{$Symbol},
13135 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013136 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013137 }
13138 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013139 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13140 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13141 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13142 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13143 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013144 {
13145 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013146 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013147 $ProblemType = "Global_Data_Symbol_Changed_Type";
13148 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013149 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13150 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013151 "Old_Type"=>$RTName1,
13152 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013153 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013154 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013155 }
13156 }
13157 }
13158 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013159 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013160 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013161 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013162 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013163 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013164 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013165 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013166 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13167 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013168 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013169 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013170 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013171 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013172 }
13173 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013174 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13175 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013176 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013177 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013178 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013179 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013180 }
13181 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013182 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013183 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013184 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013185 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013186 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013187 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013188 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013189 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013190 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013191 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013192 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013193 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013194 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013195 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013196 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013197 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013198 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013199 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013200 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013201 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013202 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013203 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013204 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013205 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013206 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013207 { # "volatile" to non-"volatile"
13208
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013209 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013210 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013211 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013212 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013213 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013214 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013215 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013216 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013217 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013218 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013219 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013220 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013221 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013222 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013223 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013224 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013225 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013226 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13227 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013228 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013229 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013230 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013231 }
13232 }
13233 }
13234 }
13235 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013236 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13237 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013238 $CurrentSymbol = $Symbol;
13239
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013240 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13241 if($Level eq "Source")
13242 { # remove symbol version
13243 $Symbol=$SN;
13244 }
13245 else
13246 { # Binary
13247 if(not $SV)
13248 { # symbol without version
13249 if(my $VSym = $SymVer{1}{$Symbol})
13250 { # the symbol is linked with versioned symbol
13251 if($CompleteSignature{2}{$VSym}{"MnglName"})
13252 { # show report for symbol@ver only
13253 next;
13254 }
13255 elsif(not link_symbol($VSym, 2, "-Deps"))
13256 { # changed version: sym@v1 to sym@v2
13257 # do NOT show report for symbol
13258 next;
13259 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013260 }
13261 }
13262 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013263 my $PSymbol = $Symbol;
13264 if($Level eq "Source"
13265 and my $S = $SourceReplacement{$Symbol})
13266 { # take a source-compatible replacement function
13267 $PSymbol = $S;
13268 }
13269 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013270 { # private symbols
13271 next;
13272 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013273 if(not defined $CompleteSignature{1}{$Symbol}
13274 or not defined $CompleteSignature{2}{$PSymbol})
13275 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013276 next;
13277 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013278 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13279 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13280 { # no mangled name
13281 next;
13282 }
13283 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13284 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013285 { # without a header
13286 next;
13287 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013288
13289 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13290 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13291 { # became pure
13292 next;
13293 }
13294 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13295 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13296 { # became non-pure
13297 next;
13298 }
13299
13300 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13301 { # exported, target, inline virtual and pure virtual
13302 next;
13303 }
13304 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13305 { # exported, target, inline virtual and pure virtual
13306 next;
13307 }
13308
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013309 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013310 {
13311 if($CompleteSignature{1}{$Symbol}{"Data"}
13312 and $CompleteSignature{2}{$PSymbol}{"Data"})
13313 {
13314 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13315 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13316 if(defined $Value1)
13317 {
13318 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13319 if(defined $Value2)
13320 {
13321 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13322 if($Value1 ne $Value2)
13323 {
13324 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13325 "Old_Value"=>$Value1,
13326 "New_Value"=>$Value2,
13327 "Target"=>get_Signature($Symbol, 1) );
13328 }
13329 }
13330 }
13331 }
13332 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013333
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013334 if($CompleteSignature{2}{$PSymbol}{"Private"})
13335 {
13336 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13337 "Target"=>get_Signature_M($PSymbol, 2) );
13338 }
13339 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13340 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13341 {
13342 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13343 "Target"=>get_Signature_M($PSymbol, 2) );
13344 }
13345 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13346 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13347 {
13348 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13349 "Target"=>get_Signature_M($PSymbol, 2) );
13350 }
13351
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013352 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013353 mergeVirtualTables($Symbol, $Level);
13354
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013355 if($COMPILE_ERRORS)
13356 { # if some errors occurred at the compiling stage
13357 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013358 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013359 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013360 { # missed information about parameters in newer version
13361 next;
13362 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013363 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013364 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013365 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013366 next;
13367 }
13368 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013369 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013370 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013371 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013372 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13373 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013374 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13375 "Target"=>get_Signature($Symbol, 1)
13376 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013377 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013378 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013379 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13380 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013381 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013382 "Target"=>get_Signature($Symbol, 1)
13383 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013384 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013385 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13386 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013387 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013388 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013389 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013390 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13391 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13392 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013393 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013394 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013395 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13396 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013397 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013398 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013399 my $ProblemType = "Virtual_Method_Position";
13400 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13401 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013402 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013403 if(isUsedClass($Class_Id, 1, $Level))
13404 {
13405 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013406 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013407 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013408 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13409 next;
13410 }
13411 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013412 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013413 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13414 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013415 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013416 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013417 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013418 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013419 }
13420 }
13421 }
13422 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013423 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13424 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013425 { # do NOT check type changes in pure virtuals
13426 next;
13427 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013428 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013429 if($Symbol=~/\A(_Z|\?)/
13430 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013431 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013432 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013433 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013434 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013435 }
13436 }
13437 else
13438 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013439 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013440 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013441 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013442 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13443 last if($PType2_Name eq "...");
13444 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13445 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013446 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013447 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013448 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013449 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13450 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013451 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13452 $ParamPos_Prev = "lost";
13453 }
13454 }
13455 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013456 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013457 }
13458 if($ParamPos_Prev eq "lost")
13459 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013460 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013461 {
13462 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013463 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013464 $ProblemType = "Added_Unnamed_Parameter";
13465 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013466 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013467 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013468 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013469 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013470 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013471 }
13472 else
13473 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013474 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013475 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013476 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013477 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13478 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013479 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013480 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013481 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013482 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013483 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013484 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013485 "Param_Type"=>$PType2_Name,
13486 "Old_Value"=>$PName_Old,
13487 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013488 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013489 }
13490 }
13491 else
13492 {
13493 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013494 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013495 $ProblemType = "Added_Middle_Unnamed_Parameter";
13496 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013497 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013498 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013499 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013500 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013501 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013502 }
13503 }
13504 }
13505 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013506 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013507 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013508 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013509 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013510 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013511 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013512 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013513 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013514 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013515 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13516 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013517 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013518 }
13519 }
13520 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013521 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013522 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013523 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013524 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13525 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013526 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13527 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013528 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013529 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013530 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013531 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13532 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013533 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13534 $ParamPos_New = "lost";
13535 }
13536 }
13537 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013538 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013539 }
13540 if($ParamPos_New eq "lost")
13541 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013542 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013543 {
13544 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013545 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013546 $ProblemType = "Removed_Unnamed_Parameter";
13547 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013548 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013549 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013550 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013551 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013552 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013553 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013554 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013555 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013556 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013557 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013558 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013559 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013560 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013561 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013562 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013563 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013564 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013565 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013566 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013567 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013568 "Old_Value"=>$PName,
13569 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013570 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013571 }
13572 }
13573 else
13574 {
13575 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013576 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013577 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13578 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013579 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013580 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013581 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013582 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013583 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013584 }
13585 }
13586 }
13587 }
13588 }
13589 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013590 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13591 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013592 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013593
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013594 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013595 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013596 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13597 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013598 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013599
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013600 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013601 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013602 if($SubProblemType eq "Return_Type_And_Size") {
13603 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13604 }
13605 elsif($SubProblemType eq "Return_Type_Format") {
13606 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13607 }
13608 else {
13609 $ProblemTypes{"Global_Data_Type"} = 1;
13610 }
13611
13612 # quals
13613 if($SubProblemType eq "Return_Type"
13614 or $SubProblemType eq "Return_Type_And_Size"
13615 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013616 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013617 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13618 { # const to non-const
13619 if($RR==2) {
13620 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13621 }
13622 else {
13623 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13624 }
13625 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013626 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013627 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13628 { # non-const to const
13629 if($RA==2) {
13630 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13631 }
13632 else {
13633 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13634 }
13635 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013636 }
13637 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013638 }
13639 else
13640 {
13641 # quals
13642 if($SubProblemType eq "Return_Type"
13643 or $SubProblemType eq "Return_Type_And_Size"
13644 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013645 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013646 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013647 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013648 if(addedQual($Old_Value, $New_Value, "volatile"))
13649 {
13650 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13651 if($Level ne "Source"
13652 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13653 $ProblemTypes{"Return_Type"} = 1;
13654 }
13655 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013656 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013657 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13658 {
13659 if($RA==2) {
13660 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13661 }
13662 else {
13663 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13664 }
13665 if($Level ne "Source"
13666 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13667 $ProblemTypes{"Return_Type"} = 1;
13668 }
13669 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013670 }
13671 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013672 if($Level eq "Binary"
13673 and not $CompleteSignature{1}{$Symbol}{"Data"})
13674 {
13675 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13676 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13677 { # if one of the architectures is unknown
13678 # then set other arhitecture to unknown too
13679 ($Arch1, $Arch2) = ("unknown", "unknown");
13680 }
13681 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013682 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013683 {
13684 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13685 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13686 }
13687 else
13688 {
13689 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13690 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13691 }
13692
13693 if($SubProblemType eq "Return_Type_Became_Void")
13694 {
13695 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13696 { # parameters stack has been affected
13697 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013698 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013699 }
13700 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013701 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013702 }
13703 }
13704 }
13705 elsif($SubProblemType eq "Return_Type_From_Void")
13706 {
13707 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13708 { # parameters stack has been affected
13709 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013710 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013711 }
13712 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013713 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013714 }
13715 }
13716 }
13717 elsif($SubProblemType eq "Return_Type"
13718 or $SubProblemType eq "Return_Type_And_Size"
13719 or $SubProblemType eq "Return_Type_Format")
13720 {
13721 if($Conv1{"Method"} ne $Conv2{"Method"})
13722 {
13723 if($Conv1{"Method"} eq "stack")
13724 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013725 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013726 }
13727 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013728 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013729 }
13730 }
13731 else
13732 {
13733 if($Conv1{"Method"} eq "reg")
13734 {
13735 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13736 {
13737 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013738 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013739 }
13740 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013741 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013742 }
13743 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013744 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013745 }
13746 }
13747 }
13748 }
13749 }
13750 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013751
13752 if(not keys(%ProblemTypes))
13753 { # default
13754 $ProblemTypes{$SubProblemType} = 1;
13755 }
13756
13757 foreach my $ProblemType (keys(%ProblemTypes))
13758 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013759 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013760 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013761 }
13762 if($ReturnType1_Id and $ReturnType2_Id)
13763 {
13764 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013765 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13766
13767 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013768
13769 if($CompleteSignature{1}{$Symbol}{"Data"})
13770 {
13771 if($Level eq "Binary")
13772 {
13773 if(get_PLevel($ReturnType1_Id, 1)==0)
13774 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013775 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013776 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013777
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013778 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13779 {
13780 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013781 {
13782 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13783 {
13784 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13785 last;
13786 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013787 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013788 }
13789 }
13790 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013791 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013792 {
13793 if(defined $GlobalDataObject{1}{$Symbol}
13794 and defined $GlobalDataObject{2}{$Symbol})
13795 {
13796 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13797 my $New_Size = $GlobalDataObject{2}{$Symbol};
13798 if($Old_Size!=$New_Size)
13799 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013800 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013801 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013802 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013803 }
13804 }
13805 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013806 }
13807 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013808
13809 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013810 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013811 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013812 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013813 my $NewLocation = "retval";
13814 if($SubLocation and $SubLocation ne "retval") {
13815 $NewLocation = "retval->".$SubLocation;
13816 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013817 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13818 }
13819 }
13820
13821 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13822 {
13823 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
13824 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013825 my $NewLocation = "retval";
13826 if($SubLocation and $SubLocation ne "retval") {
13827 $NewLocation = "retval->".$SubLocation;
13828 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013829 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013830 }
13831 }
13832 }
13833
13834 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013835 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13836 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13837 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013838 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013839 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013840 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13841 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013842 if($ThisPtr1_Id and $ThisPtr2_Id)
13843 {
13844 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013845 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
13846 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013847 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013848 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013849 {
13850 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013851 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013852 }
13853 }
13854 }
13855 }
13856 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013857 if($Level eq "Binary") {
13858 mergeVTables($Level);
13859 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013860 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
13861 $CheckedSymbols{$Level}{$Symbol} = 1;
13862 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013863}
13864
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013865sub rmQuals($$)
13866{
13867 my ($Value, $Qual) = @_;
13868 if(not $Qual) {
13869 return $Value;
13870 }
13871 if($Qual eq "all")
13872 { # all quals
13873 $Qual = "const|volatile|restrict";
13874 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013875 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013876 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013877 }
13878 return $Value;
13879}
13880
13881sub cmpBTypes($$$$)
13882{
13883 my ($T1, $T2, $V1, $V2) = @_;
13884 $T1 = uncover_typedefs($T1, $V1);
13885 $T2 = uncover_typedefs($T2, $V2);
13886 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
13887}
13888
13889sub addedQual($$$)
13890{
13891 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013892 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013893}
13894
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013895sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013896{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013897 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013898 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013899}
13900
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013901sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013902{
13903 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
13904 $Old_Value = uncover_typedefs($Old_Value, $V1);
13905 $New_Value = uncover_typedefs($New_Value, $V2);
13906 if($Old_Value eq $New_Value)
13907 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013908 return 0;
13909 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013910 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013911 { # without a qual
13912 return 0;
13913 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013914 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013915 { # became non-qual
13916 return 1;
13917 }
13918 else
13919 {
13920 my @BQ1 = getQualModel($Old_Value, $Qual);
13921 my @BQ2 = getQualModel($New_Value, $Qual);
13922 foreach (0 .. $#BQ1)
13923 { # removed qual
13924 if($BQ1[$_]==1
13925 and $BQ2[$_]!=1)
13926 {
13927 return 2;
13928 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013929 }
13930 }
13931 return 0;
13932}
13933
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013934sub getQualModel($$)
13935{
13936 my ($Value, $Qual) = @_;
13937 if(not $Qual) {
13938 return $Value;
13939 }
13940
13941 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013942 while($Value=~/(\w+)/ and $1 ne $Qual) {
13943 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013944 }
13945 $Value=~s/[^\*\&\w]+//g;
13946
13947 # modeling
13948 # int*const*const == 011
13949 # int**const == 001
13950 my @Model = ();
13951 my @Elems = split(/[\*\&]/, $Value);
13952 if(not @Elems) {
13953 return (0);
13954 }
13955 foreach (@Elems)
13956 {
13957 if($_ eq $Qual) {
13958 push(@Model, 1);
13959 }
13960 else {
13961 push(@Model, 0);
13962 }
13963 }
13964
13965 return @Model;
13966}
13967
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013968my %StringTypes = map {$_=>1} (
13969 "char*",
13970 "char const*"
13971);
13972
13973my %CharTypes = map {$_=>1} (
13974 "char",
13975 "char const"
13976);
13977
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013978sub showVal($$$)
13979{
13980 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013981 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040013982 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040013983 if(substr($Value, 0, 2) eq "_Z")
13984 {
13985 if(my $Unmangled = $tr_name{$Value}) {
13986 return $Unmangled;
13987 }
13988 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013989 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013990 { # strings
13991 return "\"$Value\"";
13992 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013993 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013994 { # characters
13995 return "\'$Value\'";
13996 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013997 if($Value eq "")
13998 { # other
13999 return "\'\'";
14000 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014001 return $Value;
14002}
14003
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014004sub getRegs($$$)
14005{
14006 my ($LibVersion, $Symbol, $Pos) = @_;
14007
14008 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14009 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014010 my %Regs = ();
14011 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14012 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014013 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014014 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14015 }
14016 }
14017
14018 return join(", ", sort keys(%Regs));
14019 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014020 elsif(defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}
14021 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}
14022 and not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}{"offset"})
14023 {
14024 return "unknown";
14025 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014026
14027 return undef;
14028}
14029
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014030sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014031{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014032 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014033 if(not $Symbol) {
14034 return;
14035 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014036 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14037 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14038 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14039 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014040 if(not $PType1_Id
14041 or not $PType2_Id) {
14042 return;
14043 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014044
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014045 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014046 { # do not merge "this"
14047 if($PName1 eq "this" or $PName2 eq "this") {
14048 return;
14049 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014050 }
14051
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014052 my %Type1 = get_Type($PType1_Id, 1);
14053 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014054
14055 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14056
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014057 my %BaseType1 = get_BaseType($PType1_Id, 1);
14058 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014059
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014060 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014061
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014062 if($Level eq "Binary")
14063 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014064 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014065 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14066 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14067 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14068 {
14069 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014070 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014071 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014072 }
14073 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14074 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14075 {
14076 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014077 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014078 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014079 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014080 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014081
14082 if(defined $UsedDump{1}{"DWARF"}
14083 and defined $UsedDump{2}{"DWARF"})
14084 {
14085 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14086 {
14087 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14088 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014089
14090 if($Old_Regs ne "unknown"
14091 and $New_Regs ne "unknown")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014092 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014093 if($Old_Regs and $New_Regs)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014094 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014095 if($Old_Regs ne $New_Regs)
14096 {
14097 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14098 "Target"=>$PName1,
14099 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14100 "Old_Value"=>$Old_Regs,
14101 "New_Value"=>$New_Regs );
14102 }
14103 }
14104 elsif($Old_Regs and not $New_Regs)
14105 {
14106 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014107 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014108 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014109 "Old_Value"=>$Old_Regs );
14110 }
14111 elsif(not $Old_Regs and $New_Regs)
14112 {
14113 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14114 "Target"=>$PName1,
14115 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014116 "New_Value"=>$New_Regs );
14117 }
14118 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014119
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014120 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14121 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14122 {
14123 if($Old_Offset ne $New_Offset)
14124 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014125 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14126 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14127
14128 $Old_Offset = $Old_Offset - $Start1;
14129 $New_Offset = $New_Offset - $Start2;
14130
14131 if($Old_Offset ne $New_Offset)
14132 {
14133 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14134 "Target"=>$PName1,
14135 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14136 "Old_Value"=>$Old_Offset,
14137 "New_Value"=>$New_Offset );
14138 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014139 }
14140 }
14141 }
14142 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014143 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014144 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14145 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014146 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014147 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014148 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14149 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014150 if(not checkDump(1, "2.13")
14151 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014152 { # support for old ABI dumps
14153 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014154 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014155 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014156 and $Value_Old eq "false" and $Value_New eq "0")
14157 { # int class::method ( bool p = 0 );
14158 # old ABI dumps: "false"
14159 # new ABI dumps: "0"
14160 $Value_Old = "0";
14161 }
14162 }
14163 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014164 if(not checkDump(1, "2.18")
14165 and checkDump(2, "2.18"))
14166 { # support for old ABI dumps
14167 if(not defined $Value_Old
14168 and substr($Value_New, 0, 2) eq "_Z") {
14169 $Value_Old = $Value_New;
14170 }
14171 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014172 if(defined $Value_Old)
14173 {
14174 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14175 if(defined $Value_New)
14176 {
14177 $Value_New = showVal($Value_New, $PType2_Id, 2);
14178 if($Value_Old ne $Value_New)
14179 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014180 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014181 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014182 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014183 "Old_Value"=>$Value_Old,
14184 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014185 }
14186 }
14187 else
14188 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014189 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014190 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014191 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014192 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014193 }
14194 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014195 elsif(defined $Value_New)
14196 {
14197 $Value_New = showVal($Value_New, $PType2_Id, 2);
14198 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14199 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014200 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014201 "New_Value"=>$Value_New );
14202 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014203 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014204
14205 if($ChkRnmd)
14206 {
14207 if($PName1 and $PName2 and $PName1 ne $PName2
14208 and $PType1_Id!=-1 and $PType2_Id!=-1
14209 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14210 { # except unnamed "..." value list (Id=-1)
14211 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14212 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014213 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014214 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14215 "Old_Value"=>$PName1,
14216 "New_Value"=>$PName2,
14217 "New_Signature"=>get_Signature($Symbol, 2) );
14218 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014219 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014220
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014221 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014222 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014223
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014224 foreach my $SubProblemType (keys(%SubProblems))
14225 { # add new problems, remove false alarms
14226 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14227 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014228
14229 # quals
14230 if($SubProblemType eq "Parameter_Type"
14231 or $SubProblemType eq "Parameter_Type_And_Size"
14232 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014233 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014234 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014235 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014236 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014237 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014238 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014239 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14240 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14241 }
14242 }
14243 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14244 {
14245 if(removedQual($Old_Value, $New_Value, "volatile")) {
14246 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014247 }
14248 }
14249 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14250 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14251 { # int to "int const"
14252 delete($SubProblems{$SubProblemType});
14253 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014254 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014255 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14256 { # "int const" to int
14257 delete($SubProblems{$SubProblemType});
14258 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014259 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14260 { # "const" to non-"const"
14261 if($RR==2) {
14262 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14263 }
14264 else {
14265 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14266 }
14267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014268 }
14269 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014270
14271 if($Level eq "Source")
14272 {
14273 foreach my $SubProblemType (keys(%SubProblems))
14274 {
14275 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14276 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14277
14278 if($SubProblemType eq "Parameter_Type")
14279 {
14280 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14281 delete($SubProblems{$SubProblemType});
14282 }
14283 }
14284 }
14285 }
14286
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014287 foreach my $SubProblemType (keys(%SubProblems))
14288 { # modify/register problems
14289 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14290 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014291 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14292 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014293
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014294 my $NewProblemType = $SubProblemType;
14295 if($Old_Value eq "..." and $New_Value ne "...")
14296 { # change from "..." to "int"
14297 if($ParamPos1==0)
14298 { # ISO C requires a named argument before "..."
14299 next;
14300 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014301 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014302 }
14303 elsif($New_Value eq "..." and $Old_Value ne "...")
14304 { # change from "int" to "..."
14305 if($ParamPos2==0)
14306 { # ISO C requires a named argument before "..."
14307 next;
14308 }
14309 $NewProblemType = "Parameter_Became_VaList";
14310 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014311 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014312 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014313 {
14314 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014315 if($Arch1 eq "unknown"
14316 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014317 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014318 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014319 ($Arch1, $Arch2) = ("unknown", "unknown");
14320 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014321 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014322 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014323 { # real
14324 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14325 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14326 }
14327 else
14328 { # model
14329 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14330 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14331 }
14332 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014333 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014334 if($Conv1{"Method"} eq "stack")
14335 {
14336 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14337 $NewProblemType = "Parameter_Type_And_Stack";
14338 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014339 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014340 elsif($Conv1{"Method"} eq "reg")
14341 {
14342 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14343 $NewProblemType = "Parameter_Type_And_Register";
14344 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014345 }
14346 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014347 elsif($Conv1{"Method"} ne "unknown"
14348 and $Conv2{"Method"} ne "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014349 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014350 if($Conv1{"Method"} eq "stack") {
14351 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014352 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014353 elsif($Conv1{"Method"} eq "register") {
14354 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014355 }
14356 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014357 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14358 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014359 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014360 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014361 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014362 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014363 "New_Signature"=>get_Signature($Symbol, 2) );
14364 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014365 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014366
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014367 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014368
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014369 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014370 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14371 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014372 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014373 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014374 {
14375 my $NewProblemType = $SubProblemType;
14376 if($SubProblemType eq "DataType_Size")
14377 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014378 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014379 { # stack has been affected
14380 $NewProblemType = "DataType_Size_And_Stack";
14381 }
14382 }
14383 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014384 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014385 }
14386 }
14387}
14388
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014389sub find_ParamPair_Pos_byName($$$)
14390{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014391 my ($Name, $Symbol, $LibVersion) = @_;
14392 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014393 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014394 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14395 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014396 {
14397 return $ParamPos;
14398 }
14399 }
14400 return "lost";
14401}
14402
14403sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14404{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014405 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014406 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014407 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014408 {
14409 next if($Order eq "backward" and $ParamPos>$MediumPos);
14410 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014411 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14412 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014413 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014414 push(@Positions, $ParamPos);
14415 }
14416 }
14417 return @Positions;
14418}
14419
14420sub getTypeIdByName($$)
14421{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014422 my ($TypeName, $LibVersion) = @_;
14423 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014424}
14425
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014426sub diffTypes($$$)
14427{
14428 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14429 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14430 }
14431 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14432 { # skip recursive declarations
14433 return 0;
14434 }
14435
14436 pushType($_[0], $_[1], \@RecurTypes_Diff);
14437 my $Diff = diffTypes_I(@_);
14438 pop(@RecurTypes_Diff);
14439
14440 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14441}
14442
14443sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014444{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014445 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014446
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014447 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14448 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014449
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014450 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14451 { # equal types
14452 return 0;
14453 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014454 if($Type1_Pure{"Name"} eq "void")
14455 { # from void* to something
14456 return 0;
14457 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014458 if($Type1_Pure{"Name"}=~/\*/
14459 or $Type2_Pure{"Name"}=~/\*/)
14460 { # compared in detectTypeChange()
14461 return 0;
14462 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014463
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014464 my %FloatType = map {$_=>1} (
14465 "float",
14466 "double",
14467 "long double"
14468 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014469
14470 my $T1 = $Type1_Pure{"Type"};
14471 my $T2 = $Type2_Pure{"Type"};
14472
14473 if($T1 eq "Struct"
14474 and $T2 eq "Class")
14475 { # compare as data structures
14476 $T2 = "Struct";
14477 }
14478
14479 if($T1 eq "Class"
14480 and $T2 eq "Struct")
14481 { # compare as data structures
14482 $T1 = "Struct";
14483 }
14484
14485 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014486 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014487 if($T1 eq "Intrinsic"
14488 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014489 { # "int" to "enum"
14490 return 0;
14491 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014492 elsif($T2 eq "Intrinsic"
14493 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014494 { # "enum" to "int"
14495 return 0;
14496 }
14497 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014498 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014499 # ...
14500 return 1;
14501 }
14502 }
14503 else
14504 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014505 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014506 {
14507 if($FloatType{$Type1_Pure{"Name"}}
14508 or $FloatType{$Type2_Pure{"Name"}})
14509 { # "float" to "double"
14510 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014511 if($Level eq "Source")
14512 { # Safe
14513 return 0;
14514 }
14515 else {
14516 return 1;
14517 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014518 }
14519 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014520 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014521 {
14522 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14523 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014524 if(not @Membs1
14525 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014526 { # private
14527 return 0;
14528 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014529 if($#Membs1!=$#Membs2)
14530 { # different number of elements
14531 return 1;
14532 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014533 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014534 {
14535 foreach my $Pos (@Membs1)
14536 { # compare elements by name and value
14537 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14538 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14539 { # different names
14540 return 1;
14541 }
14542 }
14543 }
14544 else
14545 {
14546 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014547 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014548 if($Level eq "Source")
14549 {
14550 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14551 { # different names
14552 return 1;
14553 }
14554 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014555
14556 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14557 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14558
14559 if($MT1{"Name"} ne $MT2{"Name"}
14560 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14561 {
14562 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14563 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14564
14565 if($PL1 ne $PL2)
14566 { # different pointer level
14567 return 1;
14568 }
14569
14570 # compare base types
14571 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14572 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14573
14574 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14575 { # different types
14576 return 1;
14577 }
14578 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014579 }
14580 }
14581 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014582 else
14583 {
14584 # TODO: arrays, etc.
14585 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014586 }
14587 return 0;
14588}
14589
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014590sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014591{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014592 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014593 if(not $Type1_Id or not $Type2_Id) {
14594 return ();
14595 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014596 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014597 my %Type1 = get_Type($Type1_Id, 1);
14598 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014599 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14600 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14601 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14602 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 +040014603
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014604 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14605 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014606 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14607 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14608 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14609 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14610 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14611 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14612 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014613 if($Type1{"Name"} eq $Type2{"Name"})
14614 {
14615 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14616 { # will be reported in mergeTypes() as typedef problem
14617 return ();
14618 }
14619 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14620 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14621 if(%Typedef_1 and %Typedef_2)
14622 {
14623 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14624 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14625 { # const Typedef
14626 return ();
14627 }
14628 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014629 }
14630 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14631 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014632 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014633 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14634 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014635 {
14636 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14637 "Old_Value"=>$Type1_Base{"Name"},
14638 "New_Value"=>$Type2_Base{"Name"},
14639 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014640 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014641 }
14642 else
14643 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014644 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014645 { # format change
14646 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14647 "Old_Value"=>$Type1_Base{"Name"},
14648 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014649 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014650 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014651 }
14652 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14653 {
14654 %{$LocalProblems{$Prefix."_BaseType"}}=(
14655 "Old_Value"=>$Type1_Base{"Name"},
14656 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014657 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014658 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014659 }
14660 }
14661 }
14662 }
14663 elsif($Type1{"Name"} ne $Type2{"Name"})
14664 { # type change
14665 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14666 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014667 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014668 and $Type1_Pure{"Name"} eq "void")
14669 {
14670 %{$LocalProblems{"Return_Type_From_Void"}}=(
14671 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014672 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014673 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014674 elsif($Prefix eq "Return"
14675 and $Type2_Pure{"Name"} eq "void")
14676 {
14677 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14678 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014679 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014680 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014681 else
14682 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014683 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014684 and $Type1{"Size"} and $Type2{"Size"}
14685 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014686 {
14687 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14688 "Old_Value"=>$Type1{"Name"},
14689 "New_Value"=>$Type2{"Name"},
14690 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014691 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014692 }
14693 else
14694 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014695 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014696 { # format change
14697 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14698 "Old_Value"=>$Type1{"Name"},
14699 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014700 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014701 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014702 }
14703 elsif(tNameLock($Type1_Id, $Type2_Id))
14704 { # FIXME: correct this condition
14705 %{$LocalProblems{$Prefix."_Type"}}=(
14706 "Old_Value"=>$Type1{"Name"},
14707 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014708 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014709 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014710 }
14711 }
14712 }
14713 }
14714 }
14715 if($Type1_PLevel!=$Type2_PLevel)
14716 {
14717 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14718 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14719 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014720 if($Level eq "Source")
14721 {
14722 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014723 "Old_Value"=>$Type1_PLevel,
14724 "New_Value"=>$Type2_PLevel);
14725 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014726 else
14727 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014728 if($Type2_PLevel>$Type1_PLevel)
14729 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014730 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14731 "Old_Value"=>$Type1_PLevel,
14732 "New_Value"=>$Type2_PLevel);
14733 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014734 else
14735 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014736 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14737 "Old_Value"=>$Type1_PLevel,
14738 "New_Value"=>$Type2_PLevel);
14739 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014740 }
14741 }
14742 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014743 if($Type1_Pure{"Type"} eq "Array"
14744 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014745 { # base_type[N] -> base_type[N]
14746 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014747 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014748 foreach my $SubProblemType (keys(%SubProblems))
14749 {
14750 $SubProblemType=~s/_Type/_BaseType/g;
14751 next if(defined $LocalProblems{$SubProblemType});
14752 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14753 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14754 }
14755 }
14756 }
14757 return %LocalProblems;
14758}
14759
14760sub tNameLock($$)
14761{
14762 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014763 my $Changed = 0;
14764 if(differentDumps("G"))
14765 { # different GCC versions
14766 $Changed = 1;
14767 }
14768 elsif(differentDumps("V"))
14769 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014770 if(not checkDump(1, "2.20")
14771 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014772 { # latest names update
14773 # 2.6: added restrict qualifier
14774 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014775 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014776 $Changed = 1;
14777 }
14778 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014779
14780 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14781 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14782
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014783 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14784 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14785
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014786 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014787 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014788 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014789 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014790 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014791 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014792 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014793 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014794 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014795 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014796 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14797 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14798 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014799 { # equal base types
14800 return 0;
14801 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014802
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014803 if(not checkDump(1, "2.13")
14804 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014805 { # broken array names in ABI dumps < 2.13
14806 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014807 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014808 return 0;
14809 }
14810 }
14811
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014812 if(not checkDump(1, "2.6")
14813 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014814 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014815 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014816 and $TN2=~/\brestrict\b/) {
14817 return 0;
14818 }
14819 }
14820
14821 if(not checkDump(1, "2.20")
14822 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014823 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014824 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14825 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014826 return 0;
14827 }
14828 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014829 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014830 else
14831 {
14832 # typedef struct {...} type_t
14833 # typedef struct type_t {...} type_t
14834 if(index($TN1, " ".$TN2)!=-1)
14835 {
14836 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
14837 return 0;
14838 }
14839 }
14840 if(index($TN2, " ".$TN1)!=-1)
14841 {
14842 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
14843 return 0;
14844 }
14845 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014846
14847 if($TT1 eq "FuncPtr"
14848 and $TT2 eq "FuncPtr")
14849 {
14850 my $TN1_C = $TN1;
14851 my $TN2_C = $TN2;
14852
14853 $TN1_C=~s/\b(struct|union) //g;
14854 $TN2_C=~s/\b(struct|union) //g;
14855
14856 if($TN1_C eq $TN2_C) {
14857 return 0;
14858 }
14859 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014860 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014861
14862 my ($N1, $N2) = ($TN1, $TN2);
14863 $N1=~s/\b(struct|union) //g;
14864 $N2=~s/\b(struct|union) //g;
14865
14866 if($N1 eq $N2)
14867 { # QList<struct QUrl> and QList<QUrl>
14868 return 0;
14869 }
14870
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014871 return 1;
14872}
14873
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014874sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014875{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014876 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014877 if(defined $Cache{"differentDumps"}{$Check}) {
14878 return $Cache{"differentDumps"}{$Check};
14879 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014880 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014881 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014882 if($Check eq "G")
14883 {
14884 if(getGccVersion(1) ne getGccVersion(2))
14885 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014886 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014887 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014888 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014889 if($Check eq "V")
14890 {
14891 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
14892 formatVersion($UsedDump{2}{"V"}, 2))!=0)
14893 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014894 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014895 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014896 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014897 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014898 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014899}
14900
14901sub formatVersion($$)
14902{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014903 my ($V, $Digits) = @_;
14904 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014905 return join(".", splice(@Elems, 0, $Digits));
14906}
14907
14908sub htmlSpecChars($)
14909{
14910 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014911 if(not $Str) {
14912 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014913 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014914 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14915 $Str=~s/</&lt;/g;
14916 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
14917 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014918 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
14919 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014920 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014921 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014922 $Str=~s/\n/<br\/>/g;
14923 $Str=~s/\"/&quot;/g;
14924 $Str=~s/\'/&#39;/g;
14925 return $Str;
14926}
14927
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014928sub xmlSpecChars($)
14929{
14930 my $Str = $_[0];
14931 if(not $Str) {
14932 return $Str;
14933 }
14934
14935 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14936 $Str=~s/</&lt;/g;
14937 $Str=~s/>/&gt;/g;
14938
14939 $Str=~s/\"/&quot;/g;
14940 $Str=~s/\'/&#39;/g;
14941
14942 return $Str;
14943}
14944
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014945sub xmlSpecChars_R($)
14946{
14947 my $Str = $_[0];
14948 if(not $Str) {
14949 return $Str;
14950 }
14951
14952 $Str=~s/&amp;/&/g;
14953 $Str=~s/&lt;/</g;
14954 $Str=~s/&gt;/>/g;
14955
14956 $Str=~s/&quot;/"/g;
14957 $Str=~s/&#39;/'/g;
14958
14959 return $Str;
14960}
14961
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014962sub black_name($)
14963{
14964 my $Name = $_[0];
14965 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
14966}
14967
14968sub highLight_Signature($)
14969{
14970 my $Signature = $_[0];
14971 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
14972}
14973
14974sub highLight_Signature_Italic_Color($)
14975{
14976 my $Signature = $_[0];
14977 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
14978}
14979
14980sub separate_symbol($)
14981{
14982 my $Symbol = $_[0];
14983 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
14984 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
14985 ($Name, $Spec, $Ver) = ($1, $2, $3);
14986 }
14987 return ($Name, $Spec, $Ver);
14988}
14989
14990sub cut_f_attrs($)
14991{
14992 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
14993 return $2;
14994 }
14995 return "";
14996}
14997
14998sub highLight_Signature_PPos_Italic($$$$$)
14999{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015000 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15001 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015002 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15003 my $Return = "";
15004 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15005 $Return = $2;
15006 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015007 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015008 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015009 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015010 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015011 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015012 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015013 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015014 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015015 }
15016 return $Signature;
15017 }
15018 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15019 $Begin.=" " if($Begin!~/ \Z/);
15020 $End = cut_f_attrs($Signature);
15021 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015022 my ($Short, $Params) = split_Signature($Signature);
15023 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015024 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015025 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015026 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015027 $Part=~s/\A\s+|\s+\Z//g;
15028 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15029 if($Part=~/\([\*]+(\w+)\)/i) {
15030 $ParamName = $1;#func-ptr
15031 }
15032 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15033 $ParamName = $1;
15034 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015035 if(not $ParamName)
15036 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015037 push(@Parts, $Part_Styled);
15038 next;
15039 }
15040 if($ItalicParams and not $TName_Tid{1}{$Part}
15041 and not $TName_Tid{2}{$Part})
15042 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015043 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015044 if($Param_Pos ne ""
15045 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015046 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015047 }
15048 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015049 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015050 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015051 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015052 }
15053 $Part_Styled=~s/,(\w)/, $1/g;
15054 push(@Parts, $Part_Styled);
15055 }
15056 if(@Parts)
15057 {
15058 foreach my $Num (0 .. $#Parts)
15059 {
15060 if($Num==$#Parts)
15061 { # add ")" to the last parameter
15062 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15063 }
15064 elsif(length($Parts[$Num])<=45) {
15065 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15066 }
15067 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015068 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015069 }
15070 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015071 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015072 }
15073 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015074 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015075 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015076 $Signature=~s!\[\]![&#160;]!g;
15077 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015078 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15079 if($SymbolVersion) {
15080 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15081 }
15082 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015083}
15084
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015085sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015086{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015087 my $Signature = $_[0];
15088 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15089 {
15090 $Signature=~s/\A\Q$ShortName\E\(//g;
15091 cut_f_attrs($Signature);
15092 $Signature=~s/\)\Z//;
15093 return ($ShortName, $Signature);
15094 }
15095
15096 # error
15097 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015098}
15099
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015100sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015101{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015102 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015103 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015104 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15105 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015106 foreach my $Pos (0 .. length($Params) - 1)
15107 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015108 my $S = substr($Params, $Pos, 1);
15109 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015110 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015111 }
15112 if($S eq "," and
15113 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015114 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015115 if($Comma)
15116 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015117 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015118 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015119 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015120 }
15121 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015122 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015123 }
15124 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015125 if(not $Sp)
15126 { # remove spaces
15127 foreach (@Parts)
15128 {
15129 s/\A //g;
15130 s/ \Z//g;
15131 }
15132 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015133 return @Parts;
15134}
15135
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015136sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015137{
15138 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015139 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015140 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015141 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15142 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015143 $Center+=length($1);
15144 }
15145 foreach my $Pos (0 .. length($Sign)-1)
15146 {
15147 my $S = substr($Sign, $Pos, 1);
15148 if($S eq $Target)
15149 {
15150 if($B{"("}==$B{")"}
15151 and $B{"<"}==$B{">"}) {
15152 return $Center;
15153 }
15154 }
15155 if(defined $B{$S}) {
15156 $B{$S}+=1;
15157 }
15158 $Center+=1;
15159 }
15160 return 0;
15161}
15162
15163sub appendFile($$)
15164{
15165 my ($Path, $Content) = @_;
15166 return if(not $Path);
15167 if(my $Dir = get_dirname($Path)) {
15168 mkpath($Dir);
15169 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015170 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015171 print FILE $Content;
15172 close(FILE);
15173}
15174
15175sub writeFile($$)
15176{
15177 my ($Path, $Content) = @_;
15178 return if(not $Path);
15179 if(my $Dir = get_dirname($Path)) {
15180 mkpath($Dir);
15181 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015182 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015183 print FILE $Content;
15184 close(FILE);
15185}
15186
15187sub readFile($)
15188{
15189 my $Path = $_[0];
15190 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015191 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015192 local $/ = undef;
15193 my $Content = <FILE>;
15194 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015195 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015196 $Content=~s/\r/\n/g;
15197 }
15198 return $Content;
15199}
15200
15201sub get_filename($)
15202{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015203 if(defined $Cache{"get_filename"}{$_[0]}) {
15204 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015205 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015206 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15207 return ($Cache{"get_filename"}{$_[0]}=$1);
15208 }
15209 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015210}
15211
15212sub get_dirname($)
15213{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015214 if(defined $Cache{"get_dirname"}{$_[0]}) {
15215 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015216 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015217 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15218 return ($Cache{"get_dirname"}{$_[0]}=$1);
15219 }
15220 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015221}
15222
15223sub separate_path($) {
15224 return (get_dirname($_[0]), get_filename($_[0]));
15225}
15226
15227sub esc($)
15228{
15229 my $Str = $_[0];
15230 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15231 return $Str;
15232}
15233
15234sub readLineNum($$)
15235{
15236 my ($Path, $Num) = @_;
15237 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015238 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015239 foreach (1 ... $Num) {
15240 <FILE>;
15241 }
15242 my $Line = <FILE>;
15243 close(FILE);
15244 return $Line;
15245}
15246
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015247sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015248{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015249 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015250 return () if(not $Path or not -f $Path);
15251 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015252 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15253 {
15254 foreach my $AttrVal (split(/;/, $1))
15255 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015256 if($AttrVal=~/(.+):(.+)/)
15257 {
15258 my ($Name, $Value) = ($1, $2);
15259 $Attributes{$Name} = $Value;
15260 }
15261 }
15262 }
15263 return \%Attributes;
15264}
15265
15266sub is_abs($) {
15267 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15268}
15269
15270sub get_abs_path($)
15271{ # abs_path() should NOT be called for absolute inputs
15272 # because it can change them
15273 my $Path = $_[0];
15274 if(not is_abs($Path)) {
15275 $Path = abs_path($Path);
15276 }
15277 return $Path;
15278}
15279
15280sub get_OSgroup()
15281{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015282 my $N = $Config{"osname"};
15283 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015284 return "macos";
15285 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015286 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015287 return "bsd";
15288 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015289 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015290 return "beos";
15291 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015292 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015293 return "symbian";
15294 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015295 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015296 return "windows";
15297 }
15298 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015299 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015300 }
15301}
15302
15303sub getGccVersion($)
15304{
15305 my $LibVersion = $_[0];
15306 if($GCC_VERSION{$LibVersion})
15307 { # dump version
15308 return $GCC_VERSION{$LibVersion};
15309 }
15310 elsif($UsedDump{$LibVersion}{"V"})
15311 { # old-version dumps
15312 return "unknown";
15313 }
15314 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15315 if(not $GccVersion) {
15316 return "unknown";
15317 }
15318 return $GccVersion;
15319}
15320
15321sub showArch($)
15322{
15323 my $Arch = $_[0];
15324 if($Arch eq "arm"
15325 or $Arch eq "mips") {
15326 return uc($Arch);
15327 }
15328 return $Arch;
15329}
15330
15331sub getArch($)
15332{
15333 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015334
15335 if($TargetArch) {
15336 return $TargetArch;
15337 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015338 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015339 { # dump
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015340 return $CPU_ARCH{$LibVersion};
15341 }
15342 elsif($UsedDump{$LibVersion}{"V"})
15343 { # old-version dumps
15344 return "unknown";
15345 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015346
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015347 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015348}
15349
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015350sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015351{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015352 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015353
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015354 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015355 if(getArch(1) ne getArch(2)
15356 or getArch(1) eq "unknown"
15357 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015358 { # don't show architecture in the header
15359 $ArchInfo="";
15360 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015361 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015362 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015363 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015364 }
15365 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015366 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015367 }
15368 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015369 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015370 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015371
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015372 my $V1 = $Descriptor{1}{"Version"};
15373 my $V2 = $Descriptor{2}{"Version"};
15374
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015375 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15376 {
15377 my $M1 = $UsedDump{1}{"M"};
15378 my $M2 = $UsedDump{2}{"M"};
15379
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015380 my $M1S = $M1;
15381 my $M2S = $M2;
15382
15383 $M1S=~s/(\.so|\.ko)\..+/$1/ig;
15384 $M2S=~s/(\.so|\.ko)\..+/$1/ig;
15385
15386 if($M1S eq $M2S
15387 and $V1 ne "X" and $V2 ne "Y")
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015388 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015389 $Title .= " report for the <span style='color:Blue;'>$M1S</span> $TargetComponent";
15390 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015391 }
15392 else
15393 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015394 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$V1."</span>)";
15395 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$V2."</span>) objects";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015396 }
15397 }
15398 else
15399 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015400 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015401 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015402 }
15403
15404 $Title .= $ArchInfo;
15405
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015406 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015407 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015408 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015409 $Title = "<h1>".$Title."</h1>\n";
15410 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015411}
15412
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015413sub get_CheckedHeaders($)
15414{
15415 my $LibVersion = $_[0];
15416
15417 my @Headers = ();
15418
15419 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15420 {
15421 my $File = get_filename($Path);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015422
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015423 if(not is_target_header($File, $LibVersion)) {
15424 next;
15425 }
15426
15427 if(skipHeader($File, $LibVersion)) {
15428 next;
15429 }
15430
15431 push(@Headers, $Path);
15432 }
15433
15434 return @Headers;
15435}
15436
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015437sub get_SourceInfo()
15438{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015439 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015440
15441 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015442 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015443 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15444 $CheckedHeaders .= "<div class='h_list'>\n";
15445 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 +040015446 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015447 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15448 my $Name = get_filename($Identity);
15449 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15450 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015451 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015452 $CheckedHeaders .= "</div>\n";
15453 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015454 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015455
15456 if(my @Sources = keys(%{$Registered_Sources{1}}))
15457 {
15458 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15459 $CheckedSources .= "<div class='h_list'>\n";
15460 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15461 {
15462 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15463 my $Name = get_filename($Identity);
15464 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15465 $CheckedSources .= $Name.$Comment."<br/>\n";
15466 }
15467 $CheckedSources .= "</div>\n";
15468 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15469 }
15470
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015471 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015472 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015473 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015474 $CheckedLibs .= "<div class='lib_list'>\n";
15475 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15476 {
15477 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15478 $CheckedLibs .= $Library."<br/>\n";
15479 }
15480 $CheckedLibs .= "</div>\n";
15481 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015482 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015483
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015484 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15485}
15486
15487sub get_ObjTitle()
15488{
15489 if(defined $UsedDump{1}{"DWARF"}) {
15490 return "Objects";
15491 }
15492 else {
15493 return ucfirst($SLIB_TYPE)." Libraries";
15494 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015495}
15496
15497sub get_TypeProblems_Count($$$)
15498{
15499 my ($TypeChanges, $TargetPriority, $Level) = @_;
15500 my $Type_Problems_Count = 0;
15501 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15502 {
15503 my %Kinds_Target = ();
15504 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15505 {
15506 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15507 {
15508 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015509 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
15510 next if($Severity ne $TargetPriority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015511 if($Kinds_Target{$Kind}{$Target}) {
15512 next;
15513 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015514
15515 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target})
15516 {
15517 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
15518 { # select a problem with the highest priority
15519 next;
15520 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015521 }
15522 $Kinds_Target{$Kind}{$Target} = 1;
15523 $Type_Problems_Count += 1;
15524 }
15525 }
15526 }
15527 return $Type_Problems_Count;
15528}
15529
15530sub get_Summary($)
15531{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015532 my $Level = $_[0];
15533 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015534 $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 +040015535 %{$RESULT{$Level}} = (
15536 "Problems"=>0,
15537 "Warnings"=>0,
15538 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015539 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015540 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015541 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015542 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015543 {
15544 if(not defined $CompatRules{$Level}{$Kind})
15545 { # unknown rule
15546 if(not $UnknownRules{$Level}{$Kind})
15547 { # only one warning
15548 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15549 $UnknownRules{$Level}{$Kind}=1;
15550 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015551 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015552 }
15553 }
15554 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015555 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15556 {
15557 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15558 {
15559 if(not defined $CompatRules{$Level}{$Kind})
15560 { # unknown rule
15561 if(not $UnknownRules{$Level}{$Kind})
15562 { # only one warning
15563 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15564 $UnknownRules{$Level}{$Kind}=1;
15565 }
15566 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15567 }
15568 }
15569 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015570 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015571 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015572 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015573 {
15574 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15575 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015576 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015577 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015578 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015579 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015580 $Added += 1;
15581 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015582 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015583 {
15584 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015585 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015586 }
15587 else
15588 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015589 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015590 $I_Other += 1;
15591 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015592 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015593 $I_Problems_High += 1;
15594 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015595 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015596 $I_Problems_Medium += 1;
15597 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015598 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015599 $I_Problems_Low += 1;
15600 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015601 if(($Severity ne "Low" or $StrictCompat)
15602 and $Severity ne "Safe") {
15603 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015604 }
15605 }
15606 }
15607 }
15608 }
15609 }
15610 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015611 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015612 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015613 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015614 {
15615 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15616 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015617 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015618 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015619 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15620 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015621 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015622 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15623
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015624 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015625 { # select a problem with the highest priority
15626 next;
15627 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015628
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015629 if(($Severity ne "Low" or $StrictCompat)
15630 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015631 {
15632 if(defined $TotalAffected{$Level}{$Interface})
15633 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015634 if($Severity_Val{$Severity}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15635 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015636 }
15637 }
15638 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015639 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015640 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015641 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015642
15643 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15644
15645 if($MaxSeverity)
15646 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015647 if($Severity_Val{$Severity}>$Severity_Val{$MaxSeverity}) {
15648 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015649 }
15650 }
15651 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015652 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015653 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015654 }
15655 }
15656 }
15657 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015658
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015659 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15660 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15661 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15662 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015663
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015664 %TypeChanges = (); # free memory
15665
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015666 # changed and removed public symbols
15667 my $SCount = keys(%{$CheckedSymbols{$Level}});
15668 if($ExtendedCheck)
15669 { # don't count external_func_0 for constants
15670 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015671 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015672 if($SCount)
15673 {
15674 my %Weight = (
15675 "High" => 100,
15676 "Medium" => 50,
15677 "Low" => 25
15678 );
15679 foreach (keys(%{$TotalAffected{$Level}})) {
15680 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015681 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015682 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015683 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015684 else {
15685 $RESULT{$Level}{"Affected"} = 0;
15686 }
15687
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015688 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15689 if($RESULT{$Level}{"Affected"}>=100) {
15690 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015691 }
15692
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015693 $RESULT{$Level}{"Problems"} += $Removed;
15694 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015695 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015696 if($StrictCompat) {
15697 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15698 }
15699 else {
15700 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15701 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015702
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015703 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015704 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015705 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015706 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015707 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015708 if($Severity eq "Safe")
15709 {
15710 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015711 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015712 elsif($Severity eq "Low")
15713 {
15714 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015715 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015716 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015717 }
15718
15719 if($C_Problems_Low)
15720 {
15721 if($StrictCompat) {
15722 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15723 }
15724 else {
15725 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015726 }
15727 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015728 if($RESULT{$Level}{"Problems"}
15729 and $RESULT{$Level}{"Affected"}) {
15730 $RESULT{$Level}{"Verdict"} = "incompatible";
15731 }
15732 else {
15733 $RESULT{$Level}{"Verdict"} = "compatible";
15734 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015735
15736 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15737 if(not $TotalTypes)
15738 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015739 $TotalTypes = keys(%{$TName_Tid{1}});
15740 }
15741
15742 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15743 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15744
15745 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15746
15747 if($ReportFormat eq "xml")
15748 { # XML
15749 # test info
15750 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15751 $TestInfo .= " <version1>\n";
15752 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015753 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015754 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15755 $TestInfo .= " </version1>\n";
15756
15757 $TestInfo .= " <version2>\n";
15758 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015759 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015760 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15761 $TestInfo .= " </version2>\n";
15762 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15763
15764 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015765 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015766 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015767 $TestResults .= " <headers>\n";
15768 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15769 {
15770 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15771 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15772 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15773 }
15774 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015775 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015776
15777 if(my @Sources = keys(%{$Registered_Sources{1}}))
15778 {
15779 $TestResults .= " <sources>\n";
15780 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15781 {
15782 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15783 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15784 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15785 }
15786 $TestResults .= " </sources>\n";
15787 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015788
15789 $TestResults .= " <libs>\n";
15790 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15791 {
15792 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15793 $TestResults .= " <name>$Library</name>\n";
15794 }
15795 $TestResults .= " </libs>\n";
15796
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015797 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015798 $TestResults .= " <types>".$TotalTypes."</types>\n";
15799
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015800 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15801 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015802 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15803
15804 # problem summary
15805 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15806 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15807
15808 $Problem_Summary .= " <problems_with_types>\n";
15809 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15810 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15811 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15812 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15813 $Problem_Summary .= " </problems_with_types>\n";
15814
15815 $Problem_Summary .= " <problems_with_symbols>\n";
15816 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15817 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15818 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015819 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015820 $Problem_Summary .= " </problems_with_symbols>\n";
15821
15822 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015823 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015824 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015825
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015826 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15827
15828 return ($TestInfo.$TestResults.$Problem_Summary, "");
15829 }
15830 else
15831 { # HTML
15832 # test info
15833 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015834 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015835
15836 if($TargetComponent eq "library") {
15837 $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
15838 }
15839 else {
15840 $TestInfo .= "<tr><th>Module Name</th><td>$TargetTitle</td></tr>\n";
15841 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015842
15843 my (@VInf1, @VInf2, $AddTestInfo) = ();
15844 if($Arch1 ne "unknown"
15845 and $Arch2 ne "unknown")
15846 { # CPU arch
15847 if($Arch1 eq $Arch2)
15848 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015849 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015850 }
15851 else
15852 { # go to the version number
15853 push(@VInf1, showArch($Arch1));
15854 push(@VInf2, showArch($Arch2));
15855 }
15856 }
15857 if($GccV1 ne "unknown"
15858 and $GccV2 ne "unknown"
15859 and $OStarget ne "windows")
15860 { # GCC version
15861 if($GccV1 eq $GccV2)
15862 { # go to the separate section
15863 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15864 }
15865 else
15866 { # go to the version number
15867 push(@VInf1, "gcc ".$GccV1);
15868 push(@VInf2, "gcc ".$GccV2);
15869 }
15870 }
15871 # show long version names with GCC version and CPU architecture name (if different)
15872 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
15873 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
15874 $TestInfo .= $AddTestInfo;
15875 #if($COMMON_LANGUAGE{1}) {
15876 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
15877 #}
15878 if($ExtendedCheck) {
15879 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
15880 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015881 if($JoinReport)
15882 {
15883 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015884 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015885 }
15886 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015887 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015888 }
15889 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015890 $TestInfo .= "</table>\n";
15891
15892 # test results
15893 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015894 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015895
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030015896 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015897 {
15898 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
15899 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
15900 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015901
15902 if(my @Sources = keys(%{$Registered_Sources{1}}))
15903 {
15904 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
15905 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
15906 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015907
15908 if(not $ExtendedCheck)
15909 {
15910 my $Libs_Link = "0";
15911 $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 +040015912 $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 +040015913 }
15914
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015915 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015916
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015917 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015918 if($JoinReport) {
15919 $META_DATA = "kind:".lc($Level).";".$META_DATA;
15920 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015921 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015922 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015923 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
15924 }
15925 else {
15926 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
15927 }
15928 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015929 $TestResults .= "</table>\n";
15930
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015931 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015932 # problem summary
15933 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015934 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015935 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
15936
15937 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015938 if($Added>0)
15939 {
15940 if($JoinReport) {
15941 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
15942 }
15943 else {
15944 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
15945 }
15946 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015947 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015948 $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 +040015949
15950 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015951 if($Removed>0)
15952 {
15953 if($JoinReport) {
15954 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
15955 }
15956 else {
15957 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
15958 }
15959 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015960 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015961 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
15962 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015963
15964 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015965 $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 +040015966 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015967 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
15968 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015969
15970 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015971 $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 +040015972 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015973 $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 +040015974
15975 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015976 $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 +040015977 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015978 $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 +040015979
15980 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015981 $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 +040015982 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015983 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
15984 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015985
15986 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015987 $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 +040015988 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015989 $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 +040015990
15991 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015992 $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 +040015993 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015994 $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 +040015995
15996 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015997 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
15998 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015999 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016000 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016001 $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 +040016002
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016003 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016004 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016005 {
16006 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016007 $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 Ponomarenko1fbbce62015-10-13 00:08:59 +030016008 $META_DATA .= "type_changes_other:$T_Other;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016009 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016010
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016011 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016012 {
16013 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016014 $Problem_Summary .= "<tr><th>Other Changes<br/>in Symbols</th><td>-</td><td".getStyle("I", "S", $I_Other).">$IS_Link</td></tr>\n";
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030016015 $META_DATA .= "interface_changes_other:$I_Other;";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016016 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016017
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016018 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016019 {
16020 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
16021 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030016022 $META_DATA .= "constant_changes_other:$C_Other;";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016023 }
16024
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016025 $META_DATA .= "tool_version:$TOOL_VERSION";
16026 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016027 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016028 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16029 }
16030}
16031
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016032sub getStyle($$$)
16033{
16034 my ($Subj, $Act, $Num) = @_;
16035 my %Style = (
16036 "A"=>"new",
16037 "R"=>"failed",
16038 "S"=>"passed",
16039 "L"=>"warning",
16040 "M"=>"failed",
16041 "H"=>"failed"
16042 );
16043 if($Num>0) {
16044 return " class='".$Style{$Act}."'";
16045 }
16046 return "";
16047}
16048
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016049sub show_number($)
16050{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016051 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016052 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016053 my $Num = cut_off_number($_[0], 2, 0);
16054 if($Num eq "0")
16055 {
16056 foreach my $P (3 .. 7)
16057 {
16058 $Num = cut_off_number($_[0], $P, 1);
16059 if($Num ne "0") {
16060 last;
16061 }
16062 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016063 }
16064 if($Num eq "0") {
16065 $Num = $_[0];
16066 }
16067 return $Num;
16068 }
16069 return $_[0];
16070}
16071
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016072sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016073{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016074 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016075 if($num!~/\./)
16076 {
16077 $num .= ".";
16078 foreach (1 .. $digs_to_cut-1) {
16079 $num .= "0";
16080 }
16081 }
16082 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16083 {
16084 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16085 $num .= "0";
16086 }
16087 }
16088 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16089 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16090 }
16091 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016092 if($z) {
16093 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16094 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016095 return $num;
16096}
16097
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016098sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016099{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016100 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016101 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016102
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016103 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016104 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16105 {
16106 my $Header = $Constants{1}{$Constant}{"Header"};
16107 if(not $Header)
16108 { # added
16109 $Header = $Constants{2}{$Constant}{"Header"}
16110 }
16111
16112 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16113 {
16114 if(not defined $CompatRules{$Level}{$Kind}) {
16115 next;
16116 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016117 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016118 next;
16119 }
16120 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16121 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016122 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016123
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016124 if($ReportFormat eq "xml")
16125 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016126 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016127 {
16128 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016129 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016130 {
16131 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016132 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16133 {
16134 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16135 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16136 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016137
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016138 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16139 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16140 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016141 if($Overcome) {
16142 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16143 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016144 $CHANGED_CONSTANTS .= " </problem>\n";
16145 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016146 $CHANGED_CONSTANTS .= " </constant>\n";
16147 }
16148 $CHANGED_CONSTANTS .= " </header>\n";
16149 }
16150 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16151 }
16152 else
16153 { # HTML
16154 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016155 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016156 {
16157 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016158 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016159 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016160 my $Report = "";
16161
16162 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16163 {
16164 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16165 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016166 $Report .= "<tr>\n<th>1</th>\n<td align='left' valign='top'>".$Change."</td>\n<td align='left' valign='top'>$Effect</td>\n</tr>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016167 $Number += 1;
16168 }
16169 if($Report)
16170 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016171 $Report = $ContentDivStart."<table class='ptable'>\n<tr>\n<th width='2%'></th>\n<th width='47%'>Change</th>\n<th>Effect</th>\n</tr>\n".$Report."</table>\n<br/>\n$ContentDivEnd\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016172 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16173 $Report = insertIDs($Report);
16174 }
16175 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016176 }
16177 $CHANGED_CONSTANTS .= "<br/>\n";
16178 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016179 if($CHANGED_CONSTANTS)
16180 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016181 my $Title = "Problems with Constants, $TargetSeverity Severity";
16182 if($TargetSeverity eq "Safe")
16183 { # Safe Changes
16184 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016185 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016186 $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 +040016187 }
16188 }
16189 return $CHANGED_CONSTANTS;
16190}
16191
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016192sub getTitle($$$)
16193{
16194 my ($Header, $Library, $NameSpace) = @_;
16195 my $Title = "";
16196 if($Library and $Library!~/\.\w+\Z/) {
16197 $Library .= " (.$LIB_EXT)";
16198 }
16199 if($Header and $Library)
16200 {
16201 $Title .= "<span class='h_name'>$Header</span>";
16202 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16203 }
16204 elsif($Library) {
16205 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16206 }
16207 elsif($Header) {
16208 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16209 }
16210 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016211 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016212 }
16213 return $Title;
16214}
16215
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016216sub get_Report_Added($)
16217{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016218 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016219 my $ADDED_INTERFACES = "";
16220 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016221 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016222 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016223 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016224 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016225 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016226 {
16227 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16228 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016229 if($Level eq "Source" and $ReportFormat eq "html")
16230 { # do not show library name in HTML report
16231 $DyLib = "";
16232 }
16233 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016234 }
16235 }
16236 }
16237 if($ReportFormat eq "xml")
16238 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016239 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016240 {
16241 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016242 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016243 {
16244 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016245 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016246 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16247 }
16248 $ADDED_INTERFACES .= " </library>\n";
16249 }
16250 $ADDED_INTERFACES .= " </header>\n";
16251 }
16252 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16253 }
16254 else
16255 { # HTML
16256 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016257 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016258 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016259 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016260 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016261 my %NameSpaceSymbols = ();
16262 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016263 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016264 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016265 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016266 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016267 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16268 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016269 foreach my $Interface (@SortedInterfaces)
16270 {
16271 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016272 my $Signature = get_Signature($Interface, 2);
16273 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016274 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016275 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016276 if($Interface=~/\A(_Z|\?)/)
16277 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016278 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016279 $ADDED_INTERFACES .= insertIDs($ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Interface</b>]</span>\n<br/>\n<br/>\n".$ContentDivEnd."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016280 }
16281 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016282 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016283 }
16284 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016285 else
16286 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016287 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016288 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016289 }
16290 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016291 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016292 }
16293 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016294 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016295 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016296 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016297 }
16298 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016299 if($ADDED_INTERFACES)
16300 {
16301 my $Anchor = "<a name='Added'></a>";
16302 if($JoinReport) {
16303 $Anchor = "<a name='".$Level."_Added'></a>";
16304 }
16305 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016306 }
16307 }
16308 return $ADDED_INTERFACES;
16309}
16310
16311sub get_Report_Removed($)
16312{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016313 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016314 my $REMOVED_INTERFACES = "";
16315 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016316 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016317 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016318 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016319 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016320 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016321 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016322 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16323 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016324 if($Level eq "Source" and $ReportFormat eq "html")
16325 { # do not show library name in HTML report
16326 $DyLib = "";
16327 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016328 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016329 }
16330 }
16331 }
16332 if($ReportFormat eq "xml")
16333 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016334 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016335 {
16336 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016337 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016338 {
16339 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016340 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16341 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016342 }
16343 $REMOVED_INTERFACES .= " </library>\n";
16344 }
16345 $REMOVED_INTERFACES .= " </header>\n";
16346 }
16347 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16348 }
16349 else
16350 { # HTML
16351 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016352 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016353 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016354 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016355 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016356 my %NameSpaceSymbols = ();
16357 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016358 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016359 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016360 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016361 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016362 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16363 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016364 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016365 {
16366 $Removed_Number += 1;
16367 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016368 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016369 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016370 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016371 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016372 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016373 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016374 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016375 $REMOVED_INTERFACES .= insertIDs($ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Symbol</b>]</span>\n<br/>\n<br/>\n".$ContentDivEnd."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016376 }
16377 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016378 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016379 }
16380 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016381 else
16382 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016383 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016384 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016385 }
16386 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016387 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016388 }
16389 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016390 }
16391 }
16392 $REMOVED_INTERFACES .= "<br/>\n";
16393 }
16394 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016395 if($REMOVED_INTERFACES)
16396 {
16397 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16398 if($JoinReport) {
16399 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16400 }
16401 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016402 }
16403 }
16404 return $REMOVED_INTERFACES;
16405}
16406
16407sub getXmlParams($$)
16408{
16409 my ($Content, $Problem) = @_;
16410 return "" if(not $Content or not $Problem);
16411 my %XMLparams = ();
16412 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16413 {
16414 my $Macro = "\@".lc($Attr);
16415 if($Content=~/\Q$Macro\E/) {
16416 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16417 }
16418 }
16419 my @PString = ();
16420 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016421 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016422 }
16423 if(@PString) {
16424 return " ".join(" ", @PString);
16425 }
16426 else {
16427 return "";
16428 }
16429}
16430
16431sub addMarkup($)
16432{
16433 my $Content = $_[0];
16434 # auto-markup
16435 $Content=~s/\n[ ]*//; # spaces
16436 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16437 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016438 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016439 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16440 if($Content=~/\ANOTE:/)
16441 { # notes
16442 $Content=~s!(NOTE):!<b>$1</b>:!g;
16443 }
16444 else {
16445 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16446 }
16447 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16448 my @Keywords = (
16449 "void",
16450 "const",
16451 "static",
16452 "restrict",
16453 "volatile",
16454 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016455 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016456 );
16457 my $MKeys = join("|", @Keywords);
16458 foreach (@Keywords) {
16459 $MKeys .= "|non-".$_;
16460 }
16461 $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 +040016462
16463 # Markdown
16464 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16465 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016466 return $Content;
16467}
16468
16469sub applyMacroses($$$$)
16470{
16471 my ($Level, $Kind, $Content, $Problem) = @_;
16472 return "" if(not $Content or not $Problem);
16473 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16474 $Content = addMarkup($Content);
16475 # macros
16476 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16477 {
16478 my $Macro = "\@".lc($Attr);
16479 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016480 if(not defined $Value
16481 or $Value eq "") {
16482 next;
16483 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016484
16485 if(index($Content, $Macro)==-1) {
16486 next;
16487 }
16488
16489 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16490 and $Kind!~/_Type_/
16491 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016492 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016493 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016494 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016495 $Value = black_name($Value);
16496 }
16497 elsif($Value=~/\s/) {
16498 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16499 }
16500 elsif($Value=~/\A\d+\Z/
16501 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16502 { # bits to bytes
16503 if($Value % $BYTE_SIZE)
16504 { # bits
16505 if($Value==1) {
16506 $Value = "<b>".$Value."</b> bit";
16507 }
16508 else {
16509 $Value = "<b>".$Value."</b> bits";
16510 }
16511 }
16512 else
16513 { # bytes
16514 $Value /= $BYTE_SIZE;
16515 if($Value==1) {
16516 $Value = "<b>".$Value."</b> byte";
16517 }
16518 else {
16519 $Value = "<b>".$Value."</b> bytes";
16520 }
16521 }
16522 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016523 else
16524 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016525 $Value = "<b>".htmlSpecChars($Value)."</b>";
16526 }
16527 $Content=~s/\Q$Macro\E/$Value/g;
16528 }
16529
16530 if($Content=~/(\A|[^\@\w])\@\w/)
16531 {
16532 if(not $IncompleteRules{$Level}{$Kind})
16533 { # only one warning
16534 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16535 $IncompleteRules{$Level}{$Kind} = 1;
16536 }
16537 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016538 return $Content;
16539}
16540
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016541sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016542{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016543 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016544 my $INTERFACE_PROBLEMS = "";
16545 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016546
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016547 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016548 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016549 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16550 if($SV and defined $CompatProblems{$Level}{$SN}) {
16551 next;
16552 }
16553 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016554 {
16555 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016556 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016557 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016558 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16559 my $DyLib = $Symbol_Library{1}{$Symbol};
16560 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016561 { # Symbol with Version
16562 $DyLib = $Symbol_Library{1}{$VSym};
16563 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016564 if(not $DyLib)
16565 { # const global data
16566 $DyLib = "";
16567 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016568 if($Level eq "Source" and $ReportFormat eq "html")
16569 { # do not show library name in HTML report
16570 $DyLib = "";
16571 }
16572 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16573 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016574 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016575 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16576 if($Severity ne $TargetSeverity) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016577 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016578 }
16579 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016580 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16581 {
16582 delete($SymbolChanges{$Symbol}{$Kind});
16583 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016584 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016585 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016586 }
16587 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016588 if(not keys(%{$SymbolChanges{$Symbol}})) {
16589 delete($SymbolChanges{$Symbol});
16590 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016591 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016592
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016593 if($ReportFormat eq "xml")
16594 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016595 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016596 {
16597 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016598 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016599 {
16600 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016601 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16602 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016603 {
16604 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16605 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16606 {
16607 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16608 {
16609 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016610 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016611
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016612 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16613 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16614 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16615 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16616 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016617 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16618 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16619 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016620 $INTERFACE_PROBLEMS .= " </problem>\n";
16621 }
16622 }
16623 $INTERFACE_PROBLEMS .= " </symbol>\n";
16624 }
16625 $INTERFACE_PROBLEMS .= " </library>\n";
16626 }
16627 $INTERFACE_PROBLEMS .= " </header>\n";
16628 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016629 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016630 }
16631 else
16632 { # HTML
16633 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016634 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016635 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016636 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016637 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016638 my (%NameSpaceSymbols, %NewSignature) = ();
16639 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016640 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016641 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016642 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016643 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016644 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016645 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} sort keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016646 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016647 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016648 my $Signature = get_Signature($Symbol, 1);
16649 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016650 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016651 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016652 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016653 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016654 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016655 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016656 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016657 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016658 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016659 }
16660 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16661 {
16662 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016663 $SYMBOL_REPORT .= "<tr>\n<th>$ProblemNum</th>\n<td align='left' valign='top'>".$Change."</td>\n<td align='left' valign='top'>".$Effect."</td>\n</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016664 $ProblemNum += 1;
16665 $ProblemsNum += 1;
16666 }
16667 }
16668 }
16669 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016670 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016671 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016672 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016673 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016674 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016675 }
16676 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016677 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016678 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016679 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16680 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16681 if($NewSignature{$Symbol})
16682 { # argument list changed to
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016683 $INTERFACE_PROBLEMS .= "\n<span class='new_sign_lbl'>changed to:</span>\n<br/>\n<span class='new_sign'>".highLight_Signature_Italic_Color($NewSignature{$Symbol})."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016684 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016685 if($Symbol=~/\A(_Z|\?)/) {
16686 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16687 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016688 $INTERFACE_PROBLEMS .= "<table class='ptable'>\n<tr>\n<th width='2%'></th>\n<th width='47%'>Change</th>\n<th>Effect</th>\n</tr>\n$SYMBOL_REPORT</table>\n<br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016689 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016690 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016691 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016692 }
16693 }
16694 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016695 $INTERFACE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016696 }
16697 }
16698 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016699
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016700 if($INTERFACE_PROBLEMS)
16701 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016702 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16703 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16704 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016705 { # Safe Changes
16706 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016707 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016708 $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 +040016709 }
16710 }
16711 return $INTERFACE_PROBLEMS;
16712}
16713
16714sub get_Report_TypeProblems($$)
16715{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016716 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016717 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016718 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016719
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016720 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016721 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016722 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016723 {
16724 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16725 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016726 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016727 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016728 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016729 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016730 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016731
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016732 if($Severity eq "Safe"
16733 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016734 next;
16735 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016736
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016737 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target})
16738 {
16739 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
16740 { # select a problem with the highest priority
16741 next;
16742 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016743 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016744
16745 $TypeChanges{$TypeName}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016746 }
16747 }
16748 }
16749 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016750
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016751 my %Kinds_Locations = ();
16752 foreach my $TypeName (keys(%TypeChanges))
16753 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016754 my %Kind_Target = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016755 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16756 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016757 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016758 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016759 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016760 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016761 { # other priority
16762 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16763 next;
16764 }
16765 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16766 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016767 if($Kind_Target{$Kind}{$Target})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016768 { # duplicate target
16769 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16770 next;
16771 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016772 $Kind_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016773 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016774 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016775 }
16776 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16777 delete($TypeChanges{$TypeName}{$Kind});
16778 }
16779 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016780 if(not keys(%{$TypeChanges{$TypeName}})) {
16781 delete($TypeChanges{$TypeName});
16782 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016783 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016784
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016785 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 +040016786 if($ReportFormat eq "xml")
16787 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016788 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016789 {
16790 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016791 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016792 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016793 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016794 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16795 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016796 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016797 {
16798 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16799 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16800 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16801 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16802 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16803 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016804 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16805 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16806 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016807 $TYPE_PROBLEMS .= " </problem>\n";
16808 }
16809 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016810 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016811 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016812 $TYPE_PROBLEMS .= showVTables($TypeName);
16813 }
16814 $TYPE_PROBLEMS .= " </type>\n";
16815 }
16816 $TYPE_PROBLEMS .= " </header>\n";
16817 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016818 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016819 }
16820 else
16821 { # HTML
16822 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016823 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016824 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016825 my (%NameSpace_Type) = ();
16826 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016827 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016828 }
16829 foreach my $NameSpace (sort keys(%NameSpace_Type))
16830 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016831 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016832 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 +040016833 foreach my $TypeName (@SortedTypes)
16834 {
16835 my $ProblemNum = 1;
16836 my $TYPE_REPORT = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016837
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016838 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16839 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016840 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016841 {
16842 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16843 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16844 {
16845 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016846 $TYPE_REPORT .= "<tr>\n<th>$ProblemNum</th>\n<td align='left' valign='top'>".$Change."</td>\n<td align='left' valign='top'>$Effect</td>\n</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016847 $ProblemNum += 1;
16848 $ProblemsNum += 1;
16849 }
16850 }
16851 }
16852 $ProblemNum -= 1;
16853 if($TYPE_REPORT)
16854 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016855 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016856 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016857 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016858 $ShowVTables = showVTables($TypeName);
16859 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016860
16861 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016862 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
16863 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
16864 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
16865 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016866 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016867 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016868 }
16869 }
16870 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016871 $TYPE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016872 }
16873 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016874
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016875 if($TYPE_PROBLEMS)
16876 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016877 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
16878 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016879 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016880 { # Safe Changes
16881 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016882 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016883 $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 +040016884 }
16885 }
16886 return $TYPE_PROBLEMS;
16887}
16888
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016889sub show_Type($$$)
16890{
16891 my ($Name, $Html, $LibVersion) = @_;
16892 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
16893 $TType = lc($TType);
16894 if($TType=~/struct|union|enum/) {
16895 $Name=~s/\A\Q$TType\E //g;
16896 }
16897 if($Html) {
16898 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
16899 }
16900 else {
16901 $Name = $TType." ".$Name;
16902 }
16903 return $Name;
16904}
16905
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016906sub get_Anchor($$$)
16907{
16908 my ($Kind, $Level, $Severity) = @_;
16909 if($JoinReport)
16910 {
16911 if($Severity eq "Safe") {
16912 return "Other_".$Level."_Changes_In_".$Kind."s";
16913 }
16914 else {
16915 return $Kind."_".$Level."_Problems_".$Severity;
16916 }
16917 }
16918 else
16919 {
16920 if($Severity eq "Safe") {
16921 return "Other_Changes_In_".$Kind."s";
16922 }
16923 else {
16924 return $Kind."_Problems_".$Severity;
16925 }
16926 }
16927}
16928
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016929sub showVTables($)
16930{
16931 my $TypeName = $_[0];
16932 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016933 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016934 if(defined $Type1{"VTable"}
16935 and keys(%{$Type1{"VTable"}}))
16936 {
16937 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016938 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016939 if(defined $Type2{"VTable"}
16940 and keys(%{$Type2{"VTable"}}))
16941 {
16942 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
16943 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016944 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016945 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016946 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
16947 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016948 }
16949 my $VTABLES = "";
16950 if($ReportFormat eq "xml")
16951 { # XML
16952 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016953 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016954 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016955 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016956 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
16957 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016958 $VTABLES .= " </entry>\n";
16959 }
16960 $VTABLES .= " </vtable>\n\n";
16961 }
16962 else
16963 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016964 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030016965 $VTABLES .= "<tr><th>Offset</th>";
16966 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016967 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016968 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016969 {
16970 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016971 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016972 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016973 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016974 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016975 $Color1 = " class='failed'";
16976 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016977 }
16978 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016979 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016980 }
16981 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016982 $VTABLES .= "<tr><th>".$Index."</th>\n";
16983 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
16984 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016985 }
16986 $VTABLES .= "</table><br/>\n";
16987 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016988 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016989 }
16990 return $VTABLES;
16991 }
16992 }
16993 return "";
16994}
16995
16996sub simpleVEntry($)
16997{
16998 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016999 if(not defined $VEntry
17000 or $VEntry eq "") {
17001 return "";
17002 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017003
17004 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017005 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17006 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17007 if($VEntry=~/\A_ZThn.+\Z/) {
17008 $VEntry = "non-virtual thunk";
17009 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017010 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017011 # support for old GCC versions
17012 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17013 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17014 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017015 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17016 return $VEntry;
17017}
17018
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017019sub adjustParamPos($$$)
17020{
17021 my ($Pos, $Symbol, $LibVersion) = @_;
17022 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17023 {
17024 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17025 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17026 {
17027 return $Pos-1;
17028 }
17029
17030 return $Pos;
17031 }
17032
17033 return undef;
17034}
17035
17036sub getParamPos($$$)
17037{
17038 my ($Name, $Symbol, $LibVersion) = @_;
17039
17040 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17041 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17042 {
17043 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17044 foreach (keys(%{$Info->{"Param"}}))
17045 {
17046 if($Info->{"Param"}{$_}{"name"} eq $Name)
17047 {
17048 return $_;
17049 }
17050 }
17051 }
17052
17053 return undef;
17054}
17055
17056sub getParamName($)
17057{
17058 my $Loc = $_[0];
17059 $Loc=~s/\->.*//g;
17060 return $Loc;
17061}
17062
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017063sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017064{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017065 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017066 my $LIMIT = 10;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017067
17068 if(defined $AffectLimit)
17069 {
17070 $LIMIT = $AffectLimit;
17071 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017072
17073 my %SymSel = ();
17074 my %SymLocKind = ();
17075
17076 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017077 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017078 if(index($Symbol, "_Z")==0
17079 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017080 { # duplicated problems for C2 constructors, D2 and D0 destructors
17081 next;
17082 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017083
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017084 foreach my $Kind (sort keys(%{$Kinds_Locations}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017085 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017086 if(not defined $CompatProblems{$Level}{$Symbol}
17087 or not defined $CompatProblems{$Level}{$Symbol}{$Kind}) {
17088 next;
17089 }
17090
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017091 foreach my $Loc (sort keys(%{$Kinds_Locations->{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017092 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017093 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017094 next;
17095 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017096
17097 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17098 if($Level eq "Source")
17099 { # remove symbol version
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017100 $Symbol = $SN;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017101 }
17102
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017103 if($SV and defined $CompatProblems{$Level}{$SN}
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017104 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017105 { # duplicated problems for versioned symbols
17106 next;
17107 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017108
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017109 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017110 if($Type_Name ne $Target_TypeName) {
17111 next;
17112 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017113
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017114 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017115 }
17116 }
17117 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017118
17119 foreach my $Symbol (sort keys(%SymLocKind))
17120 {
17121 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17122 {
17123 foreach my $Kind (keys(%{$SymLocKind{$Symbol}{$Loc}}))
17124 {
17125 $SymSel{$Symbol}{"Loc"} = $Loc;
17126 $SymSel{$Symbol}{"Kind"} = $Kind;
17127
17128 last LOOP;
17129 }
17130 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017131 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017132
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017133 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017134 my $Num = 0;
17135
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017136 if($ReportFormat eq "xml")
17137 { # XML
17138 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017139
17140 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017141 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017142 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017143 my $PName = getParamName($Loc);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017144 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017145
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017146 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017147 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017148 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017149 $Target .= " param=\"$PName\"";
17150 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017151 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017152 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017153 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017154 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017155 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017156 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017157 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017158
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017159 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017160 $Target .= " field=\"$1\"";
17161 }
17162
17163 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017164 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017165 $Affected .= " </symbol>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017166
17167 if($Num>$LIMIT) {
17168 last LOOP;
17169 }
17170
17171 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017172 }
17173 $Affected .= " </affected>\n";
17174 }
17175 else
17176 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017177 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017178 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017179 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $SymSel{$Symbol}{"Loc"});
17180 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017181 my $PName = getParamName($SymSel{$Symbol}{"Loc"});
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017182 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17183
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017184 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017185 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
17186
17187 if($Num>$LIMIT) {
17188 last;
17189 }
17190
17191 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017192 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017193
17194 if(keys(%SymSel)>$LIMIT) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017195 $Affected .= " ...\n<br/>\n"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017196 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017197
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017198 $Affected = "<div class='affected'>".$Affected."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017199 if($Affected)
17200 {
17201 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017202 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".keys(%SymSel).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017203 }
17204 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017205
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017206 return $Affected;
17207}
17208
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017209sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017210{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017211 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017212 if($L2=~/\A(retval|this)\b/
17213 and $L1!~/\A(retval|this)\b/)
17214 {
17215 if($L1!~/\-\>/) {
17216 return 1;
17217 }
17218 elsif($L2=~/\-\>/) {
17219 return 1;
17220 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017221 }
17222 return 0;
17223}
17224
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017225sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017226{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017227 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017228
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017229 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017230
17231 my $Location_I = $Location;
17232 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17233
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017234 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017235
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017236 if($Kind eq "Overridden_Virtual_Method"
17237 or $Kind eq "Overridden_Virtual_Method_B") {
17238 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17239 }
17240 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17241 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017242 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17243
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017244 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17245 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017246 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17247 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17248
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017249 if($ClassName eq $Problem{"Type_Name"}) {
17250 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17251 }
17252 else {
17253 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17254 }
17255 }
17256 else
17257 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017258 my $TypeID = undef;
17259
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017260 if($Location=~/retval/)
17261 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017262 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017263 push(@Sentence, "Field \'".$Location."\' in return value");
17264 }
17265 else {
17266 push(@Sentence, "Return value");
17267 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017268
17269 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017270 }
17271 elsif($Location=~/this/)
17272 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017273 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017274 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17275 }
17276 else {
17277 push(@Sentence, "\'this\' pointer");
17278 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017279
17280 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017281 }
17282 else
17283 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017284
17285 my $PName = getParamName($Location);
17286 my $PPos = getParamPos($PName, $Symbol, 1);
17287
17288 if(index($Location, "->")!=-1) {
17289 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017290 }
17291 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017292 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017293 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017294 if($PName) {
17295 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017296 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017297
17298 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17299 }
17300
17301 if($Location!~/this/)
17302 {
17303 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017304 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017305 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017306 push(@Sentence, "(pointer)");
17307 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017308 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017309 push(@Sentence, "(reference)");
17310 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017311 }
17312 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017313
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017314 if($Location eq "this") {
17315 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17316 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017317 else
17318 {
17319 my $Location_T = $Location;
17320 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17321
17322 my $TypeID_Problem = $TypeID;
17323 if($Location_T) {
17324 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17325 }
17326
17327 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17328 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17329 }
17330 else {
17331 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17332 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017333 }
17334 }
17335 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017336 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017337 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 +040017338 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017339
17340 my $Sent = join(" ", @Sentence);
17341
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017342 $Sent=~s/->/./g;
17343
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017344 if($ReportFormat eq "xml")
17345 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017346 $Sent=~s/'//g;
17347 }
17348
17349 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017350}
17351
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017352sub getFieldType($$$)
17353{
17354 my ($Location, $TypeId, $LibVersion) = @_;
17355
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017356 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017357
17358 foreach my $Name (@Fields)
17359 {
17360 my %Info = get_BaseType($TypeId, $LibVersion);
17361
17362 foreach my $Pos (keys(%{$Info{"Memb"}}))
17363 {
17364 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17365 {
17366 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17367 last;
17368 }
17369 }
17370 }
17371
17372 return $TypeId;
17373}
17374
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017375sub get_XmlSign($$)
17376{
17377 my ($Symbol, $LibVersion) = @_;
17378 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17379 my $Report = "";
17380 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17381 {
17382 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017383 my $Type = $Info->{"Param"}{$Pos}{"type"};
17384 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017385 foreach my $Typedef (keys(%ChangedTypedef))
17386 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017387 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17388 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17389 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017390 }
17391 $Report .= " <param pos=\"$Pos\">\n";
17392 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017393 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017394 $Report .= " </param>\n";
17395 }
17396 if(my $Return = $Info->{"Return"})
17397 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017398 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017399 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017400 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017401 $Report .= " </retval>\n";
17402 }
17403 return $Report;
17404}
17405
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017406sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017407{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017408 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017409 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017410 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017411 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017412 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17413 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017414 next;
17415 }
17416 $Report .= " <symbol name=\"$Symbol\">\n";
17417 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017418 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017419 {
17420 if(defined $CompleteSignature{1}{$Symbol}
17421 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17422 {
17423 $P1 = get_XmlSign($Symbol, 1);
17424 $S1 = get_Signature($Symbol, 1);
17425 }
17426 elsif($Symbol=~/\A(_Z|\?)/) {
17427 $S1 = $tr_name{$Symbol};
17428 }
17429 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017430 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017431 {
17432 if(defined $CompleteSignature{2}{$Symbol}
17433 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17434 {
17435 $P2 = get_XmlSign($Symbol, 2);
17436 $S2 = get_Signature($Symbol, 2);
17437 }
17438 elsif($Symbol=~/\A(_Z|\?)/) {
17439 $S2 = $tr_name{$Symbol};
17440 }
17441 }
17442 if($S1)
17443 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017444 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017445 $Report .= $P1;
17446 $Report .= " </old>\n";
17447 }
17448 if($S2 and $S2 ne $S1)
17449 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017450 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017451 $Report .= $P2;
17452 $Report .= " </new>\n";
17453 }
17454 $Report .= " </symbol>\n";
17455 }
17456 $Report .= "</symbols_info>\n";
17457 return $Report;
17458}
17459
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017460sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017461{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017462 my ($Level, $Report) = @_;
17463 if($ReportFormat eq "xml") {
17464 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017465 }
17466 if($StdOut)
17467 { # --stdout option
17468 print STDOUT $Report;
17469 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017470 else
17471 {
17472 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017473 mkpath(get_dirname($RPath));
17474
17475 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17476 print REPORT $Report;
17477 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017478 }
17479}
17480
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017481sub getReport($)
17482{
17483 my $Level = $_[0];
17484 if($ReportFormat eq "xml")
17485 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017486 if($Level eq "Join")
17487 {
17488 my $Report = "<reports>\n";
17489 $Report .= getReport("Binary");
17490 $Report .= getReport("Source");
17491 $Report .= "</reports>\n";
17492 return $Report;
17493 }
17494 else
17495 {
17496 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17497 my ($Summary, $MetaData) = get_Summary($Level);
17498 $Report .= $Summary."\n";
17499 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17500 $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 +040017501
17502 # additional symbols info (if needed)
17503 # $Report .= get_Report_SymbolsInfo($Level);
17504
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017505 $Report .= "</report>\n";
17506 return $Report;
17507 }
17508 }
17509 else
17510 { # HTML
17511 my $CssStyles = readModule("Styles", "Report.css");
17512 my $JScripts = readModule("Scripts", "Sections.js");
17513 if($Level eq "Join")
17514 {
17515 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17516 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017517 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017518 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17519 my $Description = "API/ABI compatibility report for the $TargetTitle $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017520 my ($BSummary, $BMetaData) = get_Summary("Binary");
17521 my ($SSummary, $SMetaData) = get_Summary("Source");
17522 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 +030017523 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017524 <br/>
17525 <div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017526 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17527 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017528 </div>";
17529 $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>";
17530 $Report .= "<div id='SourceTab' class='tab'>\n$SSummary\n".get_Report_Added("Source").get_Report_Removed("Source").get_Report_Problems("High", "Source").get_Report_Problems("Medium", "Source").get_Report_Problems("Low", "Source").get_Report_Problems("Safe", "Source").get_SourceInfo()."<br/><br/><br/></div>";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017531 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017532 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017533 return $Report;
17534 }
17535 else
17536 {
17537 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017538 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17539 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17540 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 +040017541 if($Level eq "Binary")
17542 {
17543 if(getArch(1) eq getArch(2)
17544 and getArch(1) ne "unknown") {
17545 $Description .= " on ".showArch(getArch(1));
17546 }
17547 }
17548 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 +030017549 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017550 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17551 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17552 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017553 $Report .= "</div>\n<br/><br/><br/>\n";
17554 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017555 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017556 return $Report;
17557 }
17558 }
17559}
17560
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017561sub getLegend()
17562{
17563 return "<br/>
17564<table class='summary'>
17565<tr>
17566 <td class='new'>added</td>
17567 <td class='passed'>compatible</td>
17568</tr>
17569<tr>
17570 <td class='warning'>warning</td>
17571 <td class='failed'>incompatible</td>
17572</tr></table>\n";
17573}
17574
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017575sub createReport()
17576{
17577 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017578 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017579 writeReport("Join", getReport("Join"));
17580 }
17581 elsif($DoubleReport)
17582 { # default
17583 writeReport("Binary", getReport("Binary"));
17584 writeReport("Source", getReport("Source"));
17585 }
17586 elsif($BinaryOnly)
17587 { # --binary
17588 writeReport("Binary", getReport("Binary"));
17589 }
17590 elsif($SourceOnly)
17591 { # --source
17592 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017593 }
17594}
17595
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017596sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017597{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017598 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017599
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017600 $Footer .= "<hr/>";
17601 $Footer .= "<div class='footer' align='right'><i>Generated on ".localtime(time);
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017602 $Footer .= " by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017603 $Footer .= "</i></div>";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017604 $Footer .= "<br/>\n";
17605
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017606 return $Footer;
17607}
17608
17609sub get_Report_Problems($$)
17610{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017611 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017612
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017613 my $Report = get_Report_TypeProblems($Severity, $Level);
17614 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017615 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017616 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017617
17618 if($Severity eq "Low" or $Severity eq "Safe") {
17619 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017620 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017621
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017622 if($ReportFormat eq "html")
17623 {
17624 if($Report)
17625 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017626 if($JoinReport)
17627 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017628 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017629 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17630 }
17631 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017632 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017633 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017634 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017635 else
17636 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017637 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017638 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17639 }
17640 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017641 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017642 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017643 }
17644 }
17645 }
17646 return $Report;
17647}
17648
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017649sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017650{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017651 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17652 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17653 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17654 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017655 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17656 <meta name=\"keywords\" content=\"$Keywords\" />
17657 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017658 <title>
17659 $Title
17660 </title>
17661 <style type=\"text/css\">
17662 $Styles
17663 </style>
17664 <script type=\"text/javascript\" language=\"JavaScript\">
17665 <!--
17666 $Scripts
17667 -->
17668 </script>
17669 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017670}
17671
17672sub insertIDs($)
17673{
17674 my $Text = $_[0];
17675 while($Text=~/CONTENT_ID/)
17676 {
17677 if(int($Content_Counter)%2) {
17678 $ContentID -= 1;
17679 }
17680 $Text=~s/CONTENT_ID/c_$ContentID/;
17681 $ContentID += 1;
17682 $Content_Counter += 1;
17683 }
17684 return $Text;
17685}
17686
17687sub checkPreprocessedUnit($)
17688{
17689 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017690 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017691 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017692 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017693
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017694 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017695 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017696 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017697 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017698 chomp($Line);
17699 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017700 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017701 $CurHeader = path_format($1, $OSgroup);
17702 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017703 $CurClass = "";
17704
17705 if(index($CurHeader, $TMP_DIR)==0) {
17706 next;
17707 }
17708
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017709 if(substr($CurHeaderName, 0, 1) eq "<")
17710 { # <built-in>, <command-line>, etc.
17711 $CurHeaderName = "";
17712 $CurHeader = "";
17713 }
17714
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017715 if($ExtraInfo)
17716 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017717 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017718 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17719 }
17720 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017721 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017722 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017723 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017724 if($CurHeaderName)
17725 {
17726 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17727 and not $Registered_Headers{$Version}{$CurHeader})
17728 { # not a target
17729 next;
17730 }
17731 if(not is_target_header($CurHeaderName, 1)
17732 and not is_target_header($CurHeaderName, 2))
17733 { # user-defined header
17734 next;
17735 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017736 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017737 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017738
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017739 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017740 {
17741 my ($Name, $Value) = ($1, $2);
17742 if(not $Constants{$Version}{$Name}{"Access"})
17743 {
17744 $Constants{$Version}{$Name}{"Access"} = "public";
17745 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017746 if($CurHeaderName) {
17747 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17748 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017749 }
17750 }
17751 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17752 $Constants{$Version}{$1}{"Access"} = "private";
17753 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017754 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017755 else
17756 {
17757 if(defined $ExtraDump)
17758 {
17759 if($Line=~/(\w+)\s*\(/)
17760 { # functions
17761 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17762 }
17763 #elsif($Line=~/(\w+)\s*;/)
17764 #{ # data
17765 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17766 #}
17767 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17768 $CurClass = $2;
17769 }
17770 }
17771 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017772 }
17773 close(PREPROC);
17774 foreach my $Constant (keys(%{$Constants{$Version}}))
17775 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017776 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17777 {
17778 delete($Constants{$Version}{$Constant});
17779 next;
17780 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017781 if(not $ExtraDump and ($Constant=~/_h\Z/i
17782 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017783 { # skip
17784 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017785 }
17786 else {
17787 delete($Constants{$Version}{$Constant}{"Access"});
17788 }
17789 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017790 if($Debug)
17791 {
17792 mkpath($DEBUG_PATH{$Version});
17793 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17794 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017795}
17796
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017797sub uncoverConstant($$)
17798{
17799 my ($LibVersion, $Constant) = @_;
17800 return "" if(not $LibVersion or not $Constant);
17801 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17802 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17803 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17804 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017805
17806 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017807 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017808 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17809 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017810 {
17811 push(@RecurConstant, $Constant);
17812 my $Uncovered = uncoverConstant($LibVersion, $Value);
17813 if($Uncovered ne "") {
17814 $Value = $Uncovered;
17815 }
17816 pop(@RecurConstant);
17817 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017818
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017819 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017820 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017821 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17822 }
17823 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17824}
17825
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017826sub simpleConstant($$)
17827{
17828 my ($LibVersion, $Value) = @_;
17829 if($Value=~/\W/)
17830 {
17831 my $Value_Copy = $Value;
17832 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
17833 {
17834 my $Word = $1;
17835 if($Value!~/$Word\s*\(/)
17836 {
17837 my $Val = uncoverConstant($LibVersion, $Word);
17838 if($Val ne "")
17839 {
17840 $Value=~s/\b$Word\b/$Val/g;
17841 }
17842 }
17843 }
17844 }
17845 return $Value;
17846}
17847
17848sub computeValue($)
17849{
17850 my $Value = $_[0];
17851
17852 if($Value=~/\A\((-?[\d]+)\)\Z/) {
17853 return $1;
17854 }
17855
17856 if($Value=~/\A[\d\-\+()]+\Z/) {
17857 return eval($Value);
17858 }
17859
17860 return $Value;
17861}
17862
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017863my %IgnoreConstant = map {$_=>1} (
17864 "VERSION",
17865 "VERSIONCODE",
17866 "VERNUM",
17867 "VERS_INFO",
17868 "PATCHLEVEL",
17869 "INSTALLPREFIX",
17870 "VBUILD",
17871 "VPATCH",
17872 "VMINOR",
17873 "BUILD_STRING",
17874 "BUILD_TIME",
17875 "PACKAGE_STRING",
17876 "PRODUCTION",
17877 "CONFIGURE_COMMAND",
17878 "INSTALLDIR",
17879 "BINDIR",
17880 "CONFIG_FILE_PATH",
17881 "DATADIR",
17882 "EXTENSION_DIR",
17883 "INCLUDE_PATH",
17884 "LIBDIR",
17885 "LOCALSTATEDIR",
17886 "SBINDIR",
17887 "SYSCONFDIR",
17888 "RELEASE",
17889 "SOURCE_ID",
17890 "SUBMINOR",
17891 "MINOR",
17892 "MINNOR",
17893 "MINORVERSION",
17894 "MAJOR",
17895 "MAJORVERSION",
17896 "MICRO",
17897 "MICROVERSION",
17898 "BINARY_AGE",
17899 "INTERFACE_AGE",
17900 "CORE_ABI",
17901 "PATCH",
17902 "COPYRIGHT",
17903 "TIMESTAMP",
17904 "REVISION",
17905 "PACKAGE_TAG",
17906 "PACKAGEDATE",
17907 "NUMVERSION",
17908 "Release",
17909 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017910);
17911
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017912sub constantFilter($$$)
17913{
17914 my ($Name, $Value, $Level) = @_;
17915
17916 if($Level eq "Binary")
17917 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017918 if($Name=~/_t\Z/)
17919 { # __malloc_ptr_t
17920 return 1;
17921 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017922 foreach (keys(%IgnoreConstant))
17923 {
17924 if($Name=~/(\A|_)$_(_|\Z)/)
17925 { # version
17926 return 1;
17927 }
17928 if(/\A[A-Z].*[a-z]\Z/)
17929 {
17930 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
17931 { # version
17932 return 1;
17933 }
17934 }
17935 }
17936 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
17937 { # version
17938 return 1;
17939 }
17940 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
17941 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
17942 return 1;
17943 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017944
17945 if($Value=~/\A["'].*['"]/i)
17946 { # string
17947 return 0;
17948 }
17949
17950 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
17951 { # static int gcry_pth_init
17952 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017953 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017954 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017955 return 1;
17956 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017957 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017958 { # foo(p)
17959 return 1;
17960 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017961 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017962 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017963 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017964 return 1;
17965 }
17966 }
17967
17968 return 0;
17969}
17970
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017971sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017972{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017973 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017974 foreach my $Constant (keys(%{$Constants{1}}))
17975 {
17976 if($SkipConstants{1}{$Constant})
17977 { # skipped by the user
17978 next;
17979 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017980
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017981 if(my $Header = $Constants{1}{$Constant}{"Header"})
17982 {
17983 if(not is_target_header($Header, 1)
17984 and not is_target_header($Header, 2))
17985 { # user-defined header
17986 next;
17987 }
17988 }
17989 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017990 next;
17991 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017992
17993 my $Old_Value = uncoverConstant(1, $Constant);
17994
17995 if(constantFilter($Constant, $Old_Value, $Level))
17996 { # separate binary and source problems
17997 next;
17998 }
17999
18000 if(not defined $Constants{2}{$Constant}{"Value"})
18001 { # removed
18002 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18003 "Target"=>$Constant,
18004 "Old_Value"=>$Old_Value );
18005 next;
18006 }
18007
18008 if($Constants{2}{$Constant}{"Value"} eq "")
18009 { # empty value
18010 # TODO: implement a rule
18011 next;
18012 }
18013
18014 my $New_Value = uncoverConstant(2, $Constant);
18015
18016 my $Old_Value_Pure = $Old_Value;
18017 my $New_Value_Pure = $New_Value;
18018
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018019 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18020 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18021 $New_Value_Pure=~s/(\W)\s+/$1/g;
18022 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018023
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018024 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018025
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018026 if($New_Value_Pure ne $Old_Value_Pure)
18027 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018028 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18029 { # complex values
18030 next;
18031 }
18032 if(computeValue($Old_Value) eq computeValue($New_Value))
18033 { # expressions
18034 next;
18035 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018036 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18037 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18038 next;
18039 }
18040 if($Old_Value eq "0" and $New_Value eq "NULL")
18041 { # 0 => NULL
18042 next;
18043 }
18044 if($Old_Value eq "NULL" and $New_Value eq "0")
18045 { # NULL => 0
18046 next;
18047 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018048 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018049 "Target"=>$Constant,
18050 "Old_Value"=>$Old_Value,
18051 "New_Value"=>$New_Value );
18052 }
18053 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018054
18055 foreach my $Constant (keys(%{$Constants{2}}))
18056 {
18057 if(not defined $Constants{1}{$Constant}{"Value"})
18058 {
18059 if($SkipConstants{2}{$Constant})
18060 { # skipped by the user
18061 next;
18062 }
18063
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018064 if(my $Header = $Constants{2}{$Constant}{"Header"})
18065 {
18066 if(not is_target_header($Header, 1)
18067 and not is_target_header($Header, 2))
18068 { # user-defined header
18069 next;
18070 }
18071 }
18072 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018073 next;
18074 }
18075
18076 my $New_Value = uncoverConstant(2, $Constant);
18077 if(not defined $New_Value or $New_Value eq "") {
18078 next;
18079 }
18080
18081 if(constantFilter($Constant, $New_Value, $Level))
18082 { # separate binary and source problems
18083 next;
18084 }
18085
18086 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18087 "Target"=>$Constant,
18088 "New_Value"=>$New_Value );
18089 }
18090 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018091}
18092
18093sub convert_integer($)
18094{
18095 my $Value = $_[0];
18096 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018097 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018098 return hex($Value);
18099 }
18100 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018101 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018102 return oct($Value);
18103 }
18104 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018105 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018106 return oct($Value);
18107 }
18108 else {
18109 return $Value;
18110 }
18111}
18112
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018113sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018114{
18115 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018116 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018117 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018118 {
18119 if($LibVersion==1)
18120 {
18121 printMsg("WARNING", "checking headers only");
18122 $CheckHeadersOnly = 1;
18123 }
18124 else {
18125 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18126 }
18127 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018128
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018129 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018130 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018131 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018132
18133 if($CheckUndefined)
18134 {
18135 my %UndefinedLibs = ();
18136
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018137 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18138
18139 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018140 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018141 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018142 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018143 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018144 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018145 if($Symbol_Library{$LibVersion}{$Symbol}
18146 or $DepSymbol_Library{$LibVersion}{$Symbol})
18147 { # exported by target library
18148 next;
18149 }
18150 if(index($Symbol, '@')!=-1)
18151 { # exported default symbol version (@@)
18152 $Symbol=~s/\@/\@\@/;
18153 if($Symbol_Library{$LibVersion}{$Symbol}
18154 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18155 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018156 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018157 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018158 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18159 $UndefinedLibs{$Path} = 1;
18160 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018161 }
18162 }
18163 }
18164 if($ExtraInfo)
18165 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018166 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018167 {
18168 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018169 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018170 foreach (@Paths)
18171 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018172 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018173 my ($Dir, $Name) = separate_path($_);
18174
18175 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018176 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018177 }
18178
18179 $Name = parse_libname($Name, "name", $OStarget);
18180 $Name=~s/\Alib//;
18181
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018182 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018183 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018184
18185 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18186 {
18187 $LibString = " -L".esc($Dir).$LibString;
18188 }
18189
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018190 writeFile($ExtraInfo."/libs-string", $LibString);
18191 }
18192 }
18193 }
18194
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018195 if($ExtraInfo) {
18196 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18197 }
18198
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018199 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018200 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018201 if($#LibPaths!=-1)
18202 {
18203 if(not keys(%{$Symbol_Library{$LibVersion}}))
18204 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018205 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018206 printMsg("WARNING", "checking headers only");
18207 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018208 }
18209 }
18210 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018211
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018212 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018213 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018214}
18215
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018216my %Prefix_Lib_Map=(
18217 # symbols for autodetecting library dependencies (by prefix)
18218 "pthread_" => ["libpthread"],
18219 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18220 "cairo_" => ["libcairo"],
18221 "gtk_" => ["libgtk-x11-2.0"],
18222 "atk_" => ["libatk-1.0"],
18223 "gdk_" => ["libgdk-x11-2.0"],
18224 "gl" => ["libGL"],
18225 "glu" => ["libGLU"],
18226 "popt" => ["libpopt"],
18227 "Py" => ["libpython"],
18228 "jpeg_" => ["libjpeg"],
18229 "BZ2_" => ["libbz2"],
18230 "Fc" => ["libfontconfig"],
18231 "Xft" => ["libXft"],
18232 "SSL_" => ["libssl"],
18233 "sem_" => ["libpthread"],
18234 "snd_" => ["libasound"],
18235 "art_" => ["libart_lgpl_2"],
18236 "dbus_g" => ["libdbus-glib-1"],
18237 "GOMP_" => ["libgomp"],
18238 "omp_" => ["libgomp"],
18239 "cms" => ["liblcms"]
18240);
18241
18242my %Pattern_Lib_Map=(
18243 "SL[a-z]" => ["libslang"]
18244);
18245
18246my %Symbol_Lib_Map=(
18247 # symbols for autodetecting library dependencies (by name)
18248 "pow" => "libm",
18249 "fmod" => "libm",
18250 "sin" => "libm",
18251 "floor" => "libm",
18252 "cos" => "libm",
18253 "dlopen" => "libdl",
18254 "deflate" => "libz",
18255 "inflate" => "libz",
18256 "move_panel" => "libpanel",
18257 "XOpenDisplay" => "libX11",
18258 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018259 "clock_gettime" => "librt",
18260 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018261);
18262
18263sub find_SymbolLibs($$)
18264{
18265 my ($LibVersion, $Symbol) = @_;
18266
18267 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18268 { # debug symbols
18269 return ();
18270 }
18271
18272 my %Paths = ();
18273
18274 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18275 {
18276 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18277 $Paths{$Path} = 1;
18278 }
18279 }
18280
18281 if(my $SymbolPrefix = getPrefix($Symbol))
18282 {
18283 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18284 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18285 }
18286
18287 if(not keys(%Paths))
18288 {
18289 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18290 {
18291 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18292 {
18293 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18294 $Paths{$Path} = 1;
18295 }
18296 }
18297 }
18298 }
18299
18300 if(not keys(%Paths))
18301 {
18302 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18303 {
18304 if($Symbol=~/\A$Prefix/)
18305 {
18306 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18307 {
18308 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18309 $Paths{$Path} = 1;
18310 }
18311 }
18312 }
18313 }
18314 }
18315
18316 if(not keys(%Paths))
18317 {
18318 if($SymbolPrefix)
18319 { # try to find a library by symbol prefix
18320 if($SymbolPrefix eq "inotify" and
18321 index($Symbol, "\@GLIBC")!=-1)
18322 {
18323 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18324 $Paths{$Path} = 1;
18325 }
18326 }
18327 else
18328 {
18329 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18330 $Paths{$Path} = 1;
18331 }
18332 }
18333 }
18334 }
18335
18336 if(my @Paths = keys(%Paths)) {
18337 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18338 }
18339 }
18340 return keys(%Paths);
18341}
18342
18343sub get_LibPath_Prefix($$)
18344{
18345 my ($LibVersion, $Prefix) = @_;
18346
18347 $Prefix = lc($Prefix);
18348 $Prefix=~s/[_]+\Z//g;
18349
18350 foreach ("-2", "2", "-1", "1", "")
18351 { # libgnome-2.so
18352 # libxml2.so
18353 # libdbus-1.so
18354 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18355 return $Path;
18356 }
18357 }
18358 return "";
18359}
18360
18361sub getPrefix($)
18362{
18363 my $Str = $_[0];
18364 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18365 { # XmuValidArea: Xmu
18366 return $1;
18367 }
18368 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18369 { # snfReadFont: snf
18370 return $1;
18371 }
18372 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18373 { # XRRTimes: XRR
18374 return $1;
18375 }
18376 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18377 { # H5HF_delete: H5
18378 return $1;
18379 }
18380 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18381 { # alarm_event_add: alarm_
18382 return $1;
18383 }
18384 elsif($Str=~/\A(([a-z])\2{1,})/i)
18385 { # ffopen
18386 return $1;
18387 }
18388 return "";
18389}
18390
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018391sub getSymbolSize($$)
18392{ # size from the shared library
18393 my ($Symbol, $LibVersion) = @_;
18394 return 0 if(not $Symbol);
18395 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18396 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18397 {
18398 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18399 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18400 {
18401 if($Size<0) {
18402 return -$Size;
18403 }
18404 }
18405 }
18406 return 0;
18407}
18408
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018409sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018410{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18411 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018412 my ($Name, $Type) = @_;
18413
18414 # single
18415 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018416 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018417 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018418 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018419 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018420
18421 # double
18422 if($Name=~/$DEFAULT_STD_PARMS/)
18423 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018424 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018425 {
18426 my ($ShortName, $FuncParams) = split_Signature($Name);
18427
18428 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18429 {
18430 if(index($FParam, "<")!=-1)
18431 {
18432 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18433 my $FParam_N = canonifyName($FParam, "T");
18434 if($FParam_N ne $FParam) {
18435 $Name=~s/\Q$FParam\E/$FParam_N/g;
18436 }
18437 }
18438 }
18439 }
18440 elsif($Type eq "T")
18441 {
18442 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18443
18444 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018445 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018446 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018447 my $FParam = $TParams[0];
18448 foreach my $Pos (1 .. $#TParams)
18449 {
18450 my $TParam = $TParams[$Pos];
18451 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18452 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18453 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018454 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018455 }
18456 }
18457 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018458 if($Type eq "S") {
18459 return formatName($Name, "S");
18460 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018461 return $Name;
18462}
18463
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018464sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018465{
18466 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018467 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018468 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018469 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018470 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018471 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018472 next if($tr_name{$Symbol});
18473 $Symbol=~s/[\@\$]+(.*)\Z//;
18474 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018475 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018476 elsif(index($Symbol, "?")==0)
18477 {
18478 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018479 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018480 }
18481 else
18482 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018483 $tr_name{$Symbol} = $Symbol;
18484 $mangled_name_gcc{$Symbol} = $Symbol;
18485 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018486 }
18487 }
18488 if($#MnglNames1 > -1)
18489 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018490 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018491 foreach my $MnglName (@MnglNames1)
18492 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018493 if(my $Unmangled = pop(@UnmangledNames))
18494 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018495 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018496 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18497 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18498 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018499 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018500 and $tr_name{$MnglName}=~/vtable for (.+)/)
18501 { # bind class name and v-table symbol
18502 my $ClassName = $1;
18503 $ClassVTable{$ClassName} = $MnglName;
18504 $VTableClass{$MnglName} = $ClassName;
18505 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018506 }
18507 }
18508 }
18509 if($#MnglNames2 > -1)
18510 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018511 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018512 foreach my $MnglName (@MnglNames2)
18513 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018514 if(my $Unmangled = pop(@UnmangledNames))
18515 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018516 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018517 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18518 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018519 }
18520 }
18521 return \%tr_name;
18522}
18523
18524sub link_symbol($$$)
18525{
18526 my ($Symbol, $RunWith, $Deps) = @_;
18527 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18528 return 1;
18529 }
18530 if($Deps eq "+Deps")
18531 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018532 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018533 return 1;
18534 }
18535 }
18536 return 0;
18537}
18538
18539sub link_symbol_internal($$$)
18540{
18541 my ($Symbol, $RunWith, $Where) = @_;
18542 return 0 if(not $Where or not $Symbol);
18543 if($Where->{$RunWith}{$Symbol})
18544 { # the exact match by symbol name
18545 return 1;
18546 }
18547 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18548 { # indirect symbol version, i.e.
18549 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018550 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018551 if($Where->{$RunWith}{$VSym}) {
18552 return 1;
18553 }
18554 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018555 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018556 if($Sym and $Ver)
18557 { # search for the symbol with the same version
18558 # or without version
18559 if($Where->{$RunWith}{$Sym})
18560 { # old: foo@v|foo@@v
18561 # new: foo
18562 return 1;
18563 }
18564 if($Where->{$RunWith}{$Sym."\@".$Ver})
18565 { # old: foo|foo@@v
18566 # new: foo@v
18567 return 1;
18568 }
18569 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18570 { # old: foo|foo@v
18571 # new: foo@@v
18572 return 1;
18573 }
18574 }
18575 return 0;
18576}
18577
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018578sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018579{
18580 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018581 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018582 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018583 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018584 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018585 my $NM = get_CmdPath("nm");
18586 if(not $NM) {
18587 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018588 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018589 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018590 while(<APP>)
18591 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018592 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018593 push(@Imported, $1);
18594 }
18595 }
18596 close(APP);
18597 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018598 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018599 {
18600 my $DumpBinCmd = get_CmdPath("dumpbin");
18601 if(not $DumpBinCmd) {
18602 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18603 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018604 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018605 while(<APP>)
18606 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018607 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18608 push(@Imported, $1);
18609 }
18610 }
18611 close(APP);
18612 }
18613 else
18614 {
18615 my $ReadelfCmd = get_CmdPath("readelf");
18616 if(not $ReadelfCmd) {
18617 exitStatus("Not_Found", "can't find \"readelf\"");
18618 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018619 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018620 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018621 while(<APP>)
18622 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018623 if(defined $symtab)
18624 { # do nothing with symtab
18625 if(index($_, "'.dynsym'")!=-1)
18626 { # dynamic table
18627 $symtab = undef;
18628 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018629 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018630 elsif(index($_, "'.symtab'")!=-1)
18631 { # symbol table
18632 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018633 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018634 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018635 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018636 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18637 if($Ndx eq "UND")
18638 { # only imported symbols
18639 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018640 }
18641 }
18642 }
18643 close(APP);
18644 }
18645 return @Imported;
18646}
18647
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018648my %ELF_BIND = map {$_=>1} (
18649 "WEAK",
18650 "GLOBAL"
18651);
18652
18653my %ELF_TYPE = map {$_=>1} (
18654 "FUNC",
18655 "IFUNC",
18656 "OBJECT",
18657 "COMMON"
18658);
18659
18660my %ELF_VIS = map {$_=>1} (
18661 "DEFAULT",
18662 "PROTECTED"
18663);
18664
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018665sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018666{ # read the line of 'readelf' output corresponding to the symbol
18667 my @Info = split(/\s+/, $_[0]);
18668 # Num: Value Size Type Bind Vis Ndx Name
18669 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018670 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018671 shift(@Info); # spaces
18672 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018673
18674 if($#Info==7)
18675 { # UND SYMBOL (N)
18676 if($Info[7]=~/\(\d+\)/) {
18677 pop(@Info);
18678 }
18679 }
18680
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018681 if($#Info!=6)
18682 { # other lines
18683 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018684 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018685 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018686 return () if(not defined $ELF_BIND{$Info[3]});
18687 return () if(not defined $ELF_VIS{$Info[4]});
18688 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18689 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18690 return ();
18691 }
18692 if($OStarget eq "symbian")
18693 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18694 if(index($Info[6], "_._.absent_export_")!=-1)
18695 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18696 return ();
18697 }
18698 $Info[6]=~s/\@.+//g; # remove version
18699 }
18700 if(index($Info[2], "0x") == 0)
18701 { # size == 0x3d158
18702 $Info[2] = hex($Info[2]);
18703 }
18704 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018705}
18706
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018707sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018708{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018709 my ($LibVersion, $Name) = @_;
18710 return "" if(not $LibVersion or not $Name);
18711 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18712 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018713 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018714 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18715}
18716
18717sub get_LibPath_I($$)
18718{
18719 my ($LibVersion, $Name) = @_;
18720 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018721 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018722 if(-f $Name)
18723 { # absolute path
18724 return $Name;
18725 }
18726 else
18727 { # broken
18728 return "";
18729 }
18730 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018731 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018732 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018733 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018734 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018735 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018736 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018737 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018738 }
18739 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18740 { # ldconfig default paths
18741 return $DefaultPath;
18742 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018743 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018744 { # search in default linker directories
18745 # and then in all system paths
18746 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018747 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018748 }
18749 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018750 if(not defined $Cache{"checkSystemFiles"}) {
18751 checkSystemFiles();
18752 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018753 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18754 return $AllObjects[0];
18755 }
18756 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18757 {
18758 if($ShortName ne $Name)
18759 { # FIXME: check this case
18760 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18761 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018762 }
18763 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018764 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018765 # can't find
18766 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018767}
18768
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018769sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018770{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018771 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18772 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018773
18774 my $Real_Path = realpath($Lib_Path);
18775
18776 if(not $Real_Path)
18777 { # broken link
18778 return ();
18779 }
18780
18781 my $Lib_Name = get_filename($Real_Path);
18782
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018783 if($ExtraInfo)
18784 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018785 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018786 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018787 }
18788
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018789 if($IsNeededLib)
18790 {
18791 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18792 return ();
18793 }
18794 }
18795 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018796 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018797
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018798 push(@RecurLib, $Lib_Name);
18799 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018800 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18801
18802 if(not $IsNeededLib)
18803 { # special cases: libstdc++ and libc
18804 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18805 {
18806 if($ShortName eq "libstdc++")
18807 { # libstdc++.so.6
18808 $STDCXX_TESTING = 1;
18809 }
18810 elsif($ShortName eq "libc")
18811 { # libc-2.11.3.so
18812 $GLIBC_TESTING = 1;
18813 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018814 }
18815 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018816 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018817 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018818 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018819 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018820 mkpath(get_dirname($DebugPath));
18821 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018822 if($OStarget eq "macos")
18823 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018824 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018825 if(not $NM) {
18826 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018827 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018828 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018829 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018830 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018831 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018832 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018833 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018834 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018835 else
18836 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018837 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018838 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018839 while(<LIB>)
18840 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018841 if($CheckUndefined)
18842 {
18843 if(not $IsNeededLib)
18844 {
18845 if(/ U _([\w\$]+)\s*\Z/)
18846 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018847 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018848 next;
18849 }
18850 }
18851 }
18852
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018853 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018854 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018855 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018856 if($IsNeededLib)
18857 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018858 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018859 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018860 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18861 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018862 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018863 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018864 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018865 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018866 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18867 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018868 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18869 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018870 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018871 setLanguage($LibVersion, "C++");
18872 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018873 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018874 }
18875 }
18876 }
18877 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018878
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018879 if($Deps)
18880 {
18881 if($LIB_TYPE eq "dynamic")
18882 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018883
18884 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018885 if(not $OtoolCmd) {
18886 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018887 }
18888
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018889 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18890 while(<LIB>)
18891 {
18892 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
18893 and $1 ne $Lib_Path) {
18894 $NeededLib{$1} = 1;
18895 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018896 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018897 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018898 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018899 }
18900 }
18901 elsif($OStarget eq "windows")
18902 { # Windows *.dll, *.lib
18903 my $DumpBinCmd = get_CmdPath("dumpbin");
18904 if(not $DumpBinCmd) {
18905 exitStatus("Not_Found", "can't find \"dumpbin\"");
18906 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018907 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018908 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018909 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018910 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018911 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018912 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018913 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018914 else
18915 { # write to pipe
18916 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018917 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018918 while(<LIB>)
18919 { # 1197 4AC 0000A620 SetThreadStackGuarantee
18920 # 1198 4AD SetThreadToken (forwarded to ...)
18921 # 3368 _o2i_ECPublicKey
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018922 # 1 0 00005B30 ??0?N = ... (with pdb)
18923 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018924 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018925 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018926 { # dynamic, static and forwarded symbols
18927 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018928 if($IsNeededLib)
18929 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018930 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018931 {
18932 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
18933 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
18934 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018935 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018936 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018937 {
18938 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
18939 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018940 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18941 {
18942 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
18943 setLanguage($LibVersion, "C++");
18944 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018945 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018946 }
18947 }
18948 }
18949 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018950
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018951 if($Deps)
18952 {
18953 if($LIB_TYPE eq "dynamic")
18954 { # dependencies
18955 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18956 while(<LIB>)
18957 {
18958 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
18959 and $1 ne $Lib_Path) {
18960 $NeededLib{path_format($1, $OSgroup)} = 1;
18961 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018962 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018963 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018964 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018965 }
18966 }
18967 else
18968 { # Unix; *.so, *.a
18969 # Symbian: *.dso, *.lib
18970 my $ReadelfCmd = get_CmdPath("readelf");
18971 if(not $ReadelfCmd) {
18972 exitStatus("Not_Found", "can't find \"readelf\"");
18973 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018974 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018975 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018976 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018977 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018978 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018979 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018980 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018981 else
18982 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018983 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018984 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018985 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018986 while(<LIB>)
18987 {
18988 if($LIB_TYPE eq "dynamic")
18989 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018990 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018991 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018992 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018993 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018994 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018995 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018996 # do nothing with symtab
18997 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018998 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018999 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019000 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019001 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019002 next;
19003 }
19004 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019005 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019006 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019007 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019008 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019009 if($CheckUndefined)
19010 {
19011 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019012 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019013 }
19014 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019015 next;
19016 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019017 if($Bind eq "WEAK")
19018 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019019 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019020 if($Weak eq "-Weak")
19021 { # skip WEAK symbols
19022 next;
19023 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019024 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019025 my $Short = $Symbol;
19026 $Short=~s/\@.+//g;
19027 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019028 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019029 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19030 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019031 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019032 if($IsNeededLib)
19033 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019034 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019035 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019036 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19037 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019038 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019039 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019040 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019041 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019042 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19043 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19044 if($Vers)
19045 {
19046 if($LIB_EXT eq "so")
19047 { # value
19048 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19049 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19050 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019051 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019052 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19053 {
19054 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19055 setLanguage($LibVersion, "C++");
19056 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019057 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019058 }
19059 }
19060 }
19061 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019062
19063 if($Deps and $LIB_TYPE eq "dynamic")
19064 { # dynamic library specifics
19065 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19066 open(LIB, $Cmd." |");
19067
19068 while(<LIB>)
19069 {
19070 if(/NEEDED.+\[([^\[\]]+)\]/)
19071 { # dependencies:
19072 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19073 $NeededLib{$1} = 1;
19074 }
19075 }
19076
19077 close(LIB);
19078 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019079 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019080 if($Vers)
19081 {
19082 if(not $IsNeededLib and $LIB_EXT eq "so")
19083 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019084 my %Found = ();
19085
19086 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019087 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019088 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019089 next if(index($Symbol,"\@")==-1);
19090 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019091 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019092 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019093 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019094 if($Symbol_SameValue ne $Symbol
19095 and index($Symbol_SameValue,"\@")==-1)
19096 {
19097 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019098 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019099 last;
19100 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019101 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019102 }
19103 }
19104
19105 # default
19106 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19107 {
19108 next if(defined $Found{$Symbol});
19109 next if(index($Symbol,"\@\@")==-1);
19110
19111 if($Symbol=~/\A([^\@]*)\@\@/
19112 and not $SymVer{$LibVersion}{$1})
19113 {
19114 $SymVer{$LibVersion}{$1} = $Symbol;
19115 $Found{$Symbol} = 1;
19116 }
19117 }
19118
19119 # non-default
19120 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19121 {
19122 next if(defined $Found{$Symbol});
19123 next if(index($Symbol,"\@")==-1);
19124
19125 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19126 and not $SymVer{$LibVersion}{$1})
19127 {
19128 $SymVer{$LibVersion}{$1} = $Symbol;
19129 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019130 }
19131 }
19132 }
19133 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019134 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019135 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019136 foreach my $DyLib (sort keys(%NeededLib))
19137 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019138 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19139
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019140 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19141 {
19142 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19143 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19144 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019145 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019146 }
19147 }
19148 pop(@RecurLib);
19149 return $Library_Symbol{$LibVersion};
19150}
19151
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019152sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019153{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019154 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019155 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019156 return keys(%Prefixes);
19157}
19158
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019159sub get_prefixes_I($$)
19160{
19161 foreach my $P (@{$_[0]})
19162 {
19163 my @Parts = reverse(split(/[\/\\]+/, $P));
19164 my $Name = $Parts[0];
19165 foreach (1 .. $#Parts)
19166 {
19167 $_[1]->{$Name}{$P} = 1;
19168 last if($_>4 or $Parts[$_] eq "include");
19169 $Name = $Parts[$_].$SLASH.$Name;
19170 }
19171 }
19172}
19173
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019174sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019175{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019176 $Cache{"checkSystemFiles"} = 1;
19177
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019178 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019179
19180 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019181 {
19182 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019183
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019184 my @Files = cmd_find($DevelPath,"f");
19185 foreach my $Link (cmd_find($DevelPath,"l"))
19186 { # add symbolic links
19187 if(-f $Link) {
19188 push(@Files, $Link);
19189 }
19190 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019191
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019192 # search for headers in /usr/lib
19193 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19194 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19195 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019196
19197 # search for libraries in /usr/lib (including symbolic links)
19198 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19199 foreach my $Path (@Libs)
19200 {
19201 my $N = get_filename($Path);
19202 $SystemObjects{$N}{$Path} = 1;
19203 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019204 }
19205 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019206
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019207 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019208 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019209 next if(not -d $DevelPath);
19210 # search for all header files in the /usr/include
19211 # with or without extension (ncurses.h, QtCore, ...)
19212 push(@SysHeaders, cmd_find($DevelPath,"f"));
19213 foreach my $Link (cmd_find($DevelPath,"l"))
19214 { # add symbolic links
19215 if(-f $Link) {
19216 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019217 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019218 }
19219 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019220 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019221}
19222
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019223sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019224{
19225 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019226 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019227 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19228 {
19229 if(not -e $Dest) {
19230 exitStatus("Access_Error", "can't access \'$Dest\'");
19231 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019232 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019233 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19234 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019235 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019236 }
19237 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019238 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019239}
19240
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019241sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019242{
19243 my ($Path, $LibVersion) = @_;
19244 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019245 my $Name = get_filename($Path);
19246 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019247 return 1;
19248 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019249 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019250 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19251 return 1;
19252 }
19253 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19254 {
19255 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19256 return 1;
19257 }
19258 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019259 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019260 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019261 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019262 return 1;
19263 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019264 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019265 return 1;
19266 }
19267 }
19268 return 0;
19269}
19270
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019271sub specificHeader($$)
19272{
19273 my ($Header, $Spec) = @_;
19274 my $Name = get_filename($Header);
19275
19276 if($Spec eq "windows")
19277 {# MS Windows
19278 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19279 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19280 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19281 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19282 my @Dirs = (
19283 "win32",
19284 "win64",
19285 "win",
19286 "windows",
19287 "msvcrt"
19288 ); # /gsf-win32/
19289 if(my $DIRs = join("|", @Dirs)) {
19290 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19291 }
19292 }
19293 elsif($Spec eq "macos")
19294 { # Mac OS
19295 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19296 }
19297
19298 return 0;
19299}
19300
19301sub skipAlienHeader($)
19302{
19303 my $Path = $_[0];
19304 my $Name = get_filename($Path);
19305 my $Dir = get_dirname($Path);
19306
19307 if($Tolerance=~/2/)
19308 { # 2 - skip internal headers
19309 my @Terms = (
19310 "p",
19311 "priv",
19312 "int",
19313 "impl",
19314 "implementation",
19315 "internal",
19316 "private",
19317 "old",
19318 "compat",
19319 "debug",
19320 "test",
19321 "gen"
19322 );
19323
19324 my @Dirs = (
19325 "private",
19326 "priv",
19327 "port",
19328 "impl",
19329 "internal",
19330 "detail",
19331 "details",
19332 "old",
19333 "compat",
19334 "debug",
19335 "config",
19336 "compiler",
19337 "platform",
19338 "test"
19339 );
19340
19341 if(my $TERMs = join("|", @Terms)) {
19342 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19343 }
19344 if(my $DIRs = join("|", @Dirs)) {
19345 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19346 }
19347
19348 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19349 }
19350
19351 if($Tolerance=~/1/)
19352 { # 1 - skip non-Linux headers
19353 if($OSgroup ne "windows")
19354 {
19355 if(specificHeader($Path, "windows")) {
19356 return 1;
19357 }
19358 }
19359 if($OSgroup ne "macos")
19360 {
19361 if(specificHeader($Path, "macos")) {
19362 return 1;
19363 }
19364 }
19365 }
19366
19367 # valid
19368 return 0;
19369}
19370
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019371sub skipHeader($$)
19372{
19373 my ($Path, $LibVersion) = @_;
19374 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019375 if(defined $Cache{"skipHeader"}{$Path}) {
19376 return $Cache{"skipHeader"}{$Path};
19377 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019378 if(defined $Tolerance and $Tolerance=~/1|2/)
19379 { # --tolerant
19380 if(skipAlienHeader($Path)) {
19381 return ($Cache{"skipHeader"}{$Path} = 1);
19382 }
19383 }
19384 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19385 return 0;
19386 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019387 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19388}
19389
19390sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019391{ # returns:
19392 # 1 - if header should NOT be included and checked
19393 # 2 - if header should NOT be included, but should be checked
19394 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019395 my $Name = get_filename($Path);
19396 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019397 return $Kind;
19398 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019399 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19400 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019401 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019402 if(index($Path, $D)!=-1)
19403 {
19404 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19405 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19406 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019407 }
19408 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019409 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19410 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019411 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019412 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19413 {
19414 if($Name=~/$P/) {
19415 return $Kind;
19416 }
19417 if($P=~/[\/\\]/ and $Path=~/$P/) {
19418 return $Kind;
19419 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019420 }
19421 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019422
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019423 return 0;
19424}
19425
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019426sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019427{
19428 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019429 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019430 { # system directory
19431 return;
19432 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019433 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019434 { # already registered
19435 return;
19436 }
19437 foreach my $Path (find_libs($Dir,"",1))
19438 {
19439 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019440 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019441 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019442 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019443 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19444}
19445
19446sub registerObject($$)
19447{
19448 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019449
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019450 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019451 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019452 if($OStarget=~/linux|bsd/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019453 {
19454 if(my $SONAME = getSONAME($Path)) {
19455 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19456 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019457 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019458 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19459 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019460 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019461
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019462 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019463 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019464 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019465 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019466 if($ObjArch ne getArch_GCC($LibVersion))
19467 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19468 $CheckedArch{$LibVersion} = 1;
19469 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 +040019470 }
19471 }
19472 }
19473}
19474
19475sub getArch_Object($)
19476{
19477 my $Path = $_[0];
19478
19479 my %MachineType = (
19480 "14C" => "x86",
19481 "8664" => "x86_64",
19482 "1C0" => "arm",
19483 "200" => "ia64"
19484 );
19485
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019486 my %ArchName = (
19487 "s390:31-bit" => "s390",
19488 "s390:64-bit" => "s390x",
19489 "powerpc:common" => "ppc32",
19490 "powerpc:common64" => "ppc64",
19491 "i386:x86-64" => "x86_64",
19492 "mips:3000" => "mips",
19493 "sparc:v8plus" => "sparcv9"
19494 );
19495
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019496 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019497 {
19498 my $DumpbinCmd = get_CmdPath("dumpbin");
19499 if(not $DumpbinCmd) {
19500 exitStatus("Not_Found", "can't find \"dumpbin\"");
19501 }
19502
19503 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19504 my $Out = `$Cmd`;
19505
19506 if($Out=~/(\w+)\smachine/)
19507 {
19508 if(my $Type = $MachineType{uc($1)})
19509 {
19510 return $Type;
19511 }
19512 }
19513 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019514 elsif($OStarget=~/linux|bsd/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019515 {
19516 my $ObjdumpCmd = get_CmdPath("objdump");
19517 if(not $ObjdumpCmd) {
19518 exitStatus("Not_Found", "can't find \"objdump\"");
19519 }
19520
19521 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019522
19523 if($OSgroup eq "windows") {
19524 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19525 }
19526 else {
19527 $Cmd = "LANG=$LOCALE ".$Cmd;
19528 }
19529 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019530
19531 if($Out=~/architecture:\s+([\w\-\:]+)/)
19532 {
19533 my $Arch = $1;
19534 if($Arch=~s/\:(.+)//)
19535 {
19536 my $Suffix = $1;
19537
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019538 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019539 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019540 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019541 }
19542 }
19543
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019544 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019545 $Arch = "x86";
19546 }
19547
19548 if($Arch eq "x86-64") {
19549 $Arch = "x86_64";
19550 }
19551
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019552 if($Arch eq "ia64-elf64") {
19553 $Arch = "ia64";
19554 }
19555
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019556 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019557 }
19558 }
19559 else
19560 { # macos, etc.
19561 # TODO
19562 }
19563
19564 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019565}
19566
19567sub getSONAME($)
19568{
19569 my $Path = $_[0];
19570 return if(not $Path);
19571 if(defined $Cache{"getSONAME"}{$Path}) {
19572 return $Cache{"getSONAME"}{$Path};
19573 }
19574 my $ObjdumpCmd = get_CmdPath("objdump");
19575 if(not $ObjdumpCmd) {
19576 exitStatus("Not_Found", "can't find \"objdump\"");
19577 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019578 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019579 if($OSgroup eq "windows") {
19580 $SonameCmd .= " | find \"SONAME\"";
19581 }
19582 else {
19583 $SonameCmd .= " | grep SONAME";
19584 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019585 if(my $SonameInfo = `$SonameCmd`)
19586 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019587 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19588 return ($Cache{"getSONAME"}{$Path} = $1);
19589 }
19590 }
19591 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019592}
19593
19594sub getSOPaths_Dest($$)
19595{
19596 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019597 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019598 return ();
19599 }
19600 if(-f $Dest)
19601 {
19602 if(not parse_libname($Dest, "name", $OStarget)) {
19603 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19604 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019605 registerObject($Dest, $LibVersion);
19606 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019607 return ($Dest);
19608 }
19609 elsif(-d $Dest)
19610 {
19611 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019612 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019613 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019614 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19615 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019616 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019617 { # all files and symlinks that match the name of a library
19618 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19619 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019620 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019621 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019622 }
19623 }
19624 }
19625 else
19626 { # search for all files and symlinks
19627 foreach my $Path (find_libs($Dest,"",""))
19628 {
19629 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019630 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019631 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019632 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019633 }
19634 if($OSgroup eq "macos")
19635 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019636 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019637 {
19638 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019639 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019640 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019641 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19642 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019643 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019644 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019645 }
19646 }
19647 }
19648 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019649 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019650 }
19651 else {
19652 return ();
19653 }
19654}
19655
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019656sub isCyclical($$)
19657{
19658 my ($Stack, $Value) = @_;
19659 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019660}
19661
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019662sub getGCC_Opts($)
19663{ # to use in module
19664 my $LibVersion = $_[0];
19665
19666 my @Opts = ();
19667
19668 if($CompilerOptions{$LibVersion})
19669 { # user-defined options
19670 push(@Opts, $CompilerOptions{$LibVersion});
19671 }
19672 if($GccOptions)
19673 { # additional
19674 push(@Opts, $GccOptions);
19675 }
19676
19677 if(@Opts) {
19678 return join(" ", @Opts);
19679 }
19680
19681 return undef;
19682}
19683
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019684sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019685{
19686 my $LibVersion = $_[0];
19687
19688 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19689 return $Cache{"getArch_GCC"}{$LibVersion};
19690 }
19691
19692 my $Arch = undef;
19693
19694 if($GCC_PATH)
19695 {
19696 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
19697
19698 my $Cmd = $GCC_PATH." test.c -o test";
19699 if(my $Opts = getGCC_Opts($LibVersion))
19700 { # user-defined options
19701 $Cmd .= " ".$Opts;
19702 }
19703
19704 chdir($TMP_DIR);
19705 system($Cmd);
19706 chdir($ORIG_DIR);
19707
19708 $Arch = getArch_Object("$TMP_DIR/test");
19709
19710 unlink("$TMP_DIR/test.c");
19711 unlink("$TMP_DIR/test");
19712 }
19713
19714 if(not $Arch) {
19715 exitStatus("Error", "can't check ARCH type");
19716 }
19717
19718 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
19719}
19720
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019721sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019722{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019723 my $LibVersion = $_[0];
19724
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019725 my $Size = undef;
19726
19727 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019728 if(my $Arch = getArch($LibVersion))
19729 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019730 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019731 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019732 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019733 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
19734 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019735 }
19736 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019737
19738 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019739 {
19740 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019741
19742 my $Cmd = $GCC_PATH." -E -dD empty.h";
19743 if(my $Opts = getGCC_Opts($LibVersion))
19744 { # user-defined options
19745 $Cmd .= " ".$Opts;
19746 }
19747
19748 chdir($TMP_DIR);
19749 my $Defines = `$Cmd`;
19750 chdir($ORIG_DIR);
19751
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019752 unlink("$TMP_DIR/empty.h");
19753
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019754 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
19755 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019756 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019757 }
19758 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
19759 { # GCC 3
19760 my $PTRDIFF = $1;
19761 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019762 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019763 }
19764 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019765 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019766 }
19767 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019768 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019769
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019770 if(not $Size) {
19771 exitStatus("Error", "can't check WORD size");
19772 }
19773
19774 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019775}
19776
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019777sub getWordSize($)
19778{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019779 return $WORD_SIZE{$_[0]};
19780}
19781
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019782sub majorVersion($)
19783{
19784 my $V = $_[0];
19785 return 0 if(not $V);
19786 my @VParts = split(/\./, $V);
19787 return $VParts[0];
19788}
19789
19790sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019791{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019792 my ($V1, $V2) = @_;
19793 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019794 my @V1Parts = split(/\./, $V1);
19795 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019796 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
19797 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019798 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
19799 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
19800 }
19801 return -1 if($#V1Parts < $#V2Parts);
19802 return 1 if($#V1Parts > $#V2Parts);
19803 return 0;
19804}
19805
19806sub read_ABI_Dump($$)
19807{
19808 my ($LibVersion, $Path) = @_;
19809 return if(not $LibVersion or not -e $Path);
19810 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019811 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019812 { # input *.abi
19813 $FilePath = $Path;
19814 }
19815 else
19816 { # input *.abi.tar.gz
19817 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019818 if(not isDump_U($FilePath)) {
19819 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19820 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019821 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019822
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019823 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019824
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019825 my $Line = readLineNum($FilePath, 0);
19826 if($Line=~/xml/)
19827 { # XML format
19828 loadModule("XmlDump");
19829 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019830 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019831 else
19832 { # Perl Data::Dumper format (default)
19833 open(DUMP, $FilePath);
19834 local $/ = undef;
19835 my $Content = <DUMP>;
19836 close(DUMP);
19837
19838 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
19839 { # remove temp file
19840 unlink($FilePath);
19841 }
19842 if($Content!~/};\s*\Z/) {
19843 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19844 }
19845 $ABI = eval($Content);
19846 if(not $ABI) {
19847 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
19848 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019849 }
19850 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019851 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019852 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019853 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019854 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019855 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019856 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019857 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030019858 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019859
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030019860 if($ABI->{"PublicABI"}) {
19861 $UsedDump{$LibVersion}{"Public"} = 1;
19862 }
19863
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019864 if($ABI->{"ABI_DUMP_VERSION"})
19865 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019866 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019867 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019868 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019869 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019870 }
19871 else
19872 { # support for old ABI dumps
19873 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019874 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019875 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019876 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019877 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030019878
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019879 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030019880 {
19881 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 +040019882 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019883
19884 if(defined $ABI->{"ABI_DUMPER_VERSION"})
19885 { # DWARF ABI Dump
19886 $UseConv_Real{$LibVersion}{"P"} = 1;
19887 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19888
19889 $UsedDump{$LibVersion}{"DWARF"} = 1;
19890
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030019891 if(not $TargetComponent_Opt)
19892 {
19893 if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
19894 $TargetComponent = "module";
19895 }
19896 else {
19897 $TargetComponent = "object";
19898 }
19899 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019900 }
19901
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019902 if(not checkDump($LibVersion, "2.11"))
19903 { # old ABI dumps
19904 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019905 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019906 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019907 { # ABI dump created with --binary option
19908 $UsedDump{$LibVersion}{"BinOnly"} = 1;
19909 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019910 else
19911 { # default
19912 $UsedDump{$LibVersion}{"SrcBin"} = 1;
19913 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019914
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019915 if(defined $ABI->{"Mode"}
19916 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019917 { # --ext option
19918 $ExtendedCheck = 1;
19919 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019920 if($ABI->{"Extra"}) {
19921 $ExtraDump = 1;
19922 }
19923
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019924 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019925 {
19926 $UsedDump{$LibVersion}{"L"} = $Lang;
19927 setLanguage($LibVersion, $Lang);
19928 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019929 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019930 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019931 }
19932 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019933 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019934 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019935 if(not $TInfo)
19936 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019937 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019938 }
19939 my %Tid_TDid = ();
19940 foreach my $TDid (keys(%{$TInfo}))
19941 {
19942 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
19943 {
19944 $MAX_ID = $Tid if($Tid>$MAX_ID);
19945 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019946 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019947 }
19948 }
19949 my %NewID = ();
19950 foreach my $Tid (keys(%Tid_TDid))
19951 {
19952 my @TDids = keys(%{$Tid_TDid{$Tid}});
19953 if($#TDids>=1)
19954 {
19955 foreach my $TDid (@TDids)
19956 {
19957 if($TDid) {
19958 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19959 }
19960 else
19961 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019962 my $ID = ++$MAX_ID;
19963
19964 $NewID{$TDid}{$Tid} = $ID;
19965 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
19966 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019967 }
19968 }
19969 }
19970 else
19971 {
19972 my $TDid = $TDids[0];
19973 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19974 }
19975 }
19976 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
19977 {
19978 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
19979 if(defined $Info{"BaseType"})
19980 {
19981 my $Bid = $Info{"BaseType"}{"Tid"};
19982 my $BDid = $Info{"BaseType"}{"TDid"};
19983 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019984 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019985 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
19986 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
19987 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019988 }
19989 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
19990 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019991 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019992 read_Machine_DumpInfo($ABI, $LibVersion);
19993 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019994 if(not $SymbolInfo{$LibVersion})
19995 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019996 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019997 }
19998 if(not keys(%{$SymbolInfo{$LibVersion}}))
19999 { # validation of old-version dumps
20000 if(not $ExtendedCheck) {
20001 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20002 }
20003 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020004 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020005 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020006 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020007 else
20008 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020009 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020010 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020011 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020012 }
20013 if(not $DepSymbols)
20014 { # Cannot reconstruct DepSymbols. This may result in false
20015 # positives if the old dump is for library 2. Not a problem if
20016 # old dumps are only from old libraries.
20017 $DepSymbols = {};
20018 }
20019 foreach my $Symbol (keys(%{$DepSymbols})) {
20020 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020022 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020023 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020024
20025 if(my $V = $TargetVersion{$LibVersion}) {
20026 $Descriptor{$LibVersion}{"Version"} = $V;
20027 }
20028 else {
20029 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20030 }
20031
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020032 if(not $SkipTypes{$LibVersion})
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020033 { # if not defined by -skip-types option
20034 if(defined $ABI->{"SkipTypes"})
20035 {
20036 foreach my $TName (keys(%{$ABI->{"SkipTypes"}}))
20037 {
20038 $SkipTypes{$LibVersion}{$TName} = 1;
20039 }
20040 }
20041 if(defined $ABI->{"OpaqueTypes"})
20042 { # support for old dumps
20043 foreach my $TName (keys(%{$ABI->{"OpaqueTypes"}}))
20044 {
20045 $SkipTypes{$LibVersion}{$TName} = 1;
20046 }
20047 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020048 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020049
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020050 if(not $SkipSymbols{$LibVersion})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020051 { # if not defined by -skip-symbols option
20052 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20053 if(not $SkipSymbols{$LibVersion})
20054 { # support for old dumps
20055 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20056 }
20057 if(not $SkipSymbols{$LibVersion})
20058 { # support for old dumps
20059 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20060 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020061 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020062 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020063
20064 if(not $TargetHeaders{$LibVersion})
20065 { # if not defined by -headers-list option
20066 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20067 }
20068
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020069 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020070 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020071 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020072 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020073 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020074 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020075
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020076 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020077 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020078
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020079 if(not checkDump($LibVersion, "2.10.1")
20080 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020081 { # support for old ABI dumps: added target headers
20082 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020083 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020084 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020085
20086 if(not $ABI->{"PublicABI"})
20087 {
20088 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20089 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20090 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020091 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020092 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020093 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020094 if(defined $ABI->{"GccConstants"})
20095 { # 3.0
20096 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20097 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20098 }
20099 }
20100
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020101 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020102 if(not $NestedNameSpaces{$LibVersion})
20103 { # support for old dumps
20104 # Cannot reconstruct NameSpaces. This may affect design
20105 # of the compatibility report.
20106 $NestedNameSpaces{$LibVersion} = {};
20107 }
20108 # target system type
20109 # needed to adopt HTML report
20110 if(not $DumpSystem)
20111 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020112 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020113 }
20114 # recreate environment
20115 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20116 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020117 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020118 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020119 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20120 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020121 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020122 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020123 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020124 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20125 {
20126 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20127 setLanguage($LibVersion, "C++");
20128 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020129 }
20130 }
20131 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020132 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20133 {
20134 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20135 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20136 }
20137 }
20138
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020139 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020140 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020141 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020142 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020143 {
20144 if(not $Symbol_Library{$LibVersion}{$MnglName}
20145 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20146 push(@VFunc, $MnglName);
20147 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020148 }
20149 }
20150 translateSymbols(@VFunc, $LibVersion);
20151 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020152 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20153
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020154 if(not checkDump($LibVersion, "3.0"))
20155 { # support for old ABI dumps
20156 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20157 {
20158 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20159 {
20160 if(ref($BaseType) eq "HASH") {
20161 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20162 }
20163 }
20164 }
20165 }
20166
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020167 if(not checkDump($LibVersion, "3.2"))
20168 { # support for old ABI dumps
20169 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20170 {
20171 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20172 {
20173 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20174 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20175 }
20176 }
20177 }
20178
20179 # repair target headers list
20180 delete($TargetHeaders{$LibVersion});
20181 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020182 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20183 }
20184 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20185 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020186 }
20187
20188 # non-target constants from anon enums
20189 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20190 {
20191 if(not $ExtraDump
20192 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20193 {
20194 delete($Constants{$LibVersion}{$Name});
20195 }
20196 }
20197 }
20198
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020199 if(not checkDump($LibVersion, "2.20"))
20200 { # support for old ABI dumps
20201 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20202 {
20203 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20204
20205 if($TType=~/Struct|Union|Enum|Typedef/)
20206 { # repair complex types first
20207 next;
20208 }
20209
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020210 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020211 {
20212 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20213 if($BType=~/Struct|Union|Enum/i)
20214 {
20215 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20216 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20217 }
20218 }
20219 }
20220 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20221 {
20222 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20223 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20224 if($TType=~/Struct|Union|Enum/) {
20225 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20226 }
20227 }
20228 }
20229
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020230 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020231 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020232 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20233 { # support for old ABI dumps < 2.0 (ACC 1.22)
20234 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20235 {
20236 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20237 {
20238 if($Access ne "public") {
20239 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20240 }
20241 }
20242 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20243 }
20244 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20245 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020246 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20247 { # support for old ABI dumps
20248 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20249 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020250 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20251 { # DWARF ABI Dumps
20252 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20253 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020254 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20255 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20256 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020257 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20258 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020259 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020260 foreach (keys(%{$TInfo{"Base"}})) {
20261 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020262 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020263 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020264 if($TInfo{"Type"} eq "MethodPtr")
20265 {
20266 if(defined $TInfo{"Param"})
20267 { # support for old ABI dumps <= 1.17
20268 if(not defined $TInfo{"Param"}{"0"})
20269 {
20270 my $Max = keys(%{$TInfo{"Param"}});
20271 foreach my $Pos (1 .. $Max) {
20272 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20273 }
20274 delete($TInfo{"Param"}{$Max});
20275 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20276 }
20277 }
20278 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020279 if($TInfo{"BaseType"} eq $TypeId)
20280 { # fix ABI dump
20281 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20282 }
20283 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020284 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020285 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020286 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020287 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20288 if(not $BName)
20289 { # broken type
20290 next;
20291 }
20292 if($TInfo{"Name"} eq $BName)
20293 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020294 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020295 next;
20296 }
20297 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20298 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020299 }
20300 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020301 }
20302 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20303 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020304 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020305 }
20306 }
20307
20308 if(not checkDump($LibVersion, "2.15"))
20309 { # support for old ABI dumps
20310 my %Dups = ();
20311 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20312 {
20313 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020314 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020315 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20316 { # remove template decls
20317 delete($SymbolInfo{$LibVersion}{$InfoId});
20318 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020319 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020320 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020321 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20322 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020323 { # templates
20324 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020325 }
20326 }
20327 }
20328
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020329 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20330 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020331 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20332 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20333 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20334 { # support for old ABI dumps (< 3.1)
20335 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20336 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20337 { # add "this" first parameter
20338 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20339 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20340
20341 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20342 {
20343 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20344 foreach my $Pos (reverse(0 .. $#Pos)) {
20345 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20346 }
20347 }
20348 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20349 }
20350 }
20351
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020352 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20353 { # ABI dumps have no mangled names for C-functions
20354 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20355 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020356 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20357 { # support for old ABI dumps
20358 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20359 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020360 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20361 { # DWARF ABI Dumps
20362 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20363 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020364 }
20365
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020366 $Descriptor{$LibVersion}{"Dump"} = 1;
20367}
20368
20369sub read_Machine_DumpInfo($$)
20370{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020371 my ($ABI, $LibVersion) = @_;
20372 if($ABI->{"Arch"}) {
20373 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020374 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020375 if($ABI->{"WordSize"}) {
20376 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020377 }
20378 else
20379 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020380 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020381 }
20382 if(not $WORD_SIZE{$LibVersion})
20383 { # support for old dumps (<1.23)
20384 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20385 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020386 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020387 }
20388 else
20389 {
20390 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020391 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020392 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020393 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20394 { # any "pointer"-type
20395 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020396 last;
20397 }
20398 }
20399 if($PSize)
20400 { # a pointer type size
20401 $WORD_SIZE{$LibVersion} = $PSize;
20402 }
20403 else {
20404 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20405 }
20406 }
20407 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020408 if($ABI->{"GccVersion"}) {
20409 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020410 }
20411}
20412
20413sub read_Libs_DumpInfo($$)
20414{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020415 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020416 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20417 if(not $Library_Symbol{$LibVersion})
20418 { # support for old dumps
20419 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20420 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020421 if(keys(%{$Library_Symbol{$LibVersion}})
20422 and not $DumpAPI) {
20423 $Descriptor{$LibVersion}{"Libs"} = "OK";
20424 }
20425}
20426
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020427sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020428{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020429 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020430
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020431 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020432 and not $DumpAPI) {
20433 $Descriptor{$LibVersion}{"Headers"} = "OK";
20434 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020435 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020436 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020437 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020438 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020439 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020440
20441 if(keys(%{$ABI->{"Sources"}})
20442 and not $DumpAPI) {
20443 $Descriptor{$LibVersion}{"Sources"} = "OK";
20444 }
20445 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020446 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020447 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20448 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20449 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020450}
20451
20452sub find_libs($$$)
20453{
20454 my ($Path, $Type, $MaxDepth) = @_;
20455 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020456 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020457}
20458
20459sub createDescriptor($$)
20460{
20461 my ($LibVersion, $Path) = @_;
20462 if(not $LibVersion or not $Path
20463 or not -e $Path) {
20464 return "";
20465 }
20466 if(-d $Path)
20467 { # directory with headers files and shared objects
20468 return "
20469 <version>
20470 ".$TargetVersion{$LibVersion}."
20471 </version>
20472
20473 <headers>
20474 $Path
20475 </headers>
20476
20477 <libs>
20478 $Path
20479 </libs>";
20480 }
20481 else
20482 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020483 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020484 { # standard XML-descriptor
20485 return readFile($Path);
20486 }
20487 elsif(is_header($Path, 2, $LibVersion))
20488 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020489 $CheckHeadersOnly = 1;
20490
20491 if($LibVersion==1) {
20492 $TargetVersion{$LibVersion} = "X";
20493 }
20494
20495 if($LibVersion==2) {
20496 $TargetVersion{$LibVersion} = "Y";
20497 }
20498
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020499 return "
20500 <version>
20501 ".$TargetVersion{$LibVersion}."
20502 </version>
20503
20504 <headers>
20505 $Path
20506 </headers>
20507
20508 <libs>
20509 none
20510 </libs>";
20511 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020512 else
20513 { # standard XML-descriptor
20514 return readFile($Path);
20515 }
20516 }
20517}
20518
20519sub detect_lib_default_paths()
20520{
20521 my %LPaths = ();
20522 if($OSgroup eq "bsd")
20523 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020524 if(my $LdConfig = get_CmdPath("ldconfig"))
20525 {
20526 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20527 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020528 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20529 {
20530 my $Name = "lib".$1;
20531 if(not defined $LPaths{$Name}) {
20532 $LPaths{$Name} = $2;
20533 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020534 }
20535 }
20536 }
20537 else {
20538 printMsg("WARNING", "can't find ldconfig");
20539 }
20540 }
20541 else
20542 {
20543 if(my $LdConfig = get_CmdPath("ldconfig"))
20544 {
20545 if($SystemRoot and $OSgroup eq "linux")
20546 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20547 if(-e $SystemRoot."/etc/ld.so.conf") {
20548 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20549 }
20550 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020551 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20552 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020553 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20554 {
20555 my ($Name, $Path) = ($1, $2);
20556 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020557 if(not defined $LPaths{$Name})
20558 { # get first element from the list of available paths
20559
20560 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20561 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20562 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20563
20564 $LPaths{$Name} = $Path;
20565 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020566 }
20567 }
20568 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020569 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020570 printMsg("WARNING", "can't find ldconfig");
20571 }
20572 }
20573 return \%LPaths;
20574}
20575
20576sub detect_bin_default_paths()
20577{
20578 my $EnvPaths = $ENV{"PATH"};
20579 if($OSgroup eq "beos") {
20580 $EnvPaths.=":".$ENV{"BETOOLS"};
20581 }
20582 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020583 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020584 {
20585 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020586 next if(not $Path);
20587 if($SystemRoot
20588 and $Path=~/\A\Q$SystemRoot\E\//)
20589 { # do NOT use binaries from target system
20590 next;
20591 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020592 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020593 }
20594}
20595
20596sub detect_inc_default_paths()
20597{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020598 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020599 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020600 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020601 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020602 next if(index($Line, "/cc1plus ")!=-1);
20603
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020604 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20605 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020606 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020607 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020608 if(index($Path, "c++")!=-1
20609 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020610 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020611 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020612 if(not defined $MAIN_CPP_DIR
20613 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20614 $MAIN_CPP_DIR = $Path;
20615 }
20616 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020617 elsif(index($Path, "gcc")!=-1) {
20618 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020619 }
20620 else
20621 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020622 if($Path=~/local[\/\\]+include/)
20623 { # local paths
20624 next;
20625 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020626 if($SystemRoot
20627 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20628 { # The GCC include path for user headers is not a part of the system root
20629 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20630 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20631 next;
20632 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020633 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020634 }
20635 }
20636 }
20637 unlink("$TMP_DIR/empty.h");
20638 return %DPaths;
20639}
20640
20641sub detect_default_paths($)
20642{
20643 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20644 my $Search = $_[0];
20645 if($Search!~/inc/) {
20646 $HSearch = 0;
20647 }
20648 if($Search!~/lib/) {
20649 $LSearch = 0;
20650 }
20651 if($Search!~/bin/) {
20652 $BSearch = 0;
20653 }
20654 if($Search!~/gcc/) {
20655 $GSearch = 0;
20656 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020657 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020658 { # <search_headers> section of the XML descriptor
20659 # do NOT search for systems headers
20660 $HSearch = 0;
20661 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020662 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030020663 { # <search_libs> section of the XML descriptor
20664 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020665 $LSearch = 0;
20666 }
20667 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20668 { # additional search paths
20669 next if($Type eq "include" and not $HSearch);
20670 next if($Type eq "lib" and not $LSearch);
20671 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020672 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020673 }
20674 if($OSgroup ne "windows")
20675 { # unix-like
20676 foreach my $Type ("include", "lib", "bin")
20677 { # automatic detection of system "devel" directories
20678 next if($Type eq "include" and not $HSearch);
20679 next if($Type eq "lib" and not $LSearch);
20680 next if($Type eq "bin" and not $BSearch);
20681 my ($UsrDir, $RootDir) = ("/usr", "/");
20682 if($SystemRoot and $Type ne "bin")
20683 { # 1. search for target headers and libraries
20684 # 2. use host commands: ldconfig, readelf, etc.
20685 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20686 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020687 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020688 if(-d $RootDir."/".$Type)
20689 { # if "/lib" is symbolic link
20690 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020691 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020692 }
20693 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020694 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020695 }
20696 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020697 if(-d $UsrDir)
20698 {
20699 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020700 if(-d $UsrDir."/".$Type)
20701 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020702 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020703 }
20704 }
20705 }
20706 }
20707 if($BSearch)
20708 {
20709 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020710 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020711 }
20712 # check environment variables
20713 if($OSgroup eq "beos")
20714 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020715 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020716 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020717 if($_ eq ".") {
20718 next;
20719 }
20720 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20721 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20722 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020723 }
20724 }
20725 if($HSearch)
20726 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020727 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20728 split(/:|;/, $ENV{"BEINCLUDES"})
20729 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020730 }
20731 if($LSearch)
20732 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020733 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20734 split(/:|;/, $ENV{"BELIBRARIES"}),
20735 split(/:|;/, $ENV{"LIBRARY_PATH"})
20736 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020737 }
20738 }
20739 if($LSearch)
20740 { # using linker to get system paths
20741 if(my $LPaths = detect_lib_default_paths())
20742 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020743 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020744 foreach my $Name (keys(%{$LPaths}))
20745 {
20746 if($SystemRoot
20747 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20748 { # wrong ldconfig configuration
20749 # check your <sysroot>/etc/ld.so.conf
20750 next;
20751 }
20752 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020753 if(my $Dir = get_dirname($LPaths->{$Name})) {
20754 $Dirs{$Dir} = 1;
20755 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020756 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020757 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020758 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020759 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020760 }
20761 if($BSearch)
20762 {
20763 if($CrossGcc)
20764 { # --cross-gcc=arm-linux-gcc
20765 if(-e $CrossGcc)
20766 { # absolute or relative path
20767 $GCC_PATH = get_abs_path($CrossGcc);
20768 }
20769 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20770 { # command name
20771 $GCC_PATH = $CrossGcc;
20772 }
20773 else {
20774 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20775 }
20776 if($GCC_PATH=~/\s/) {
20777 $GCC_PATH = "\"".$GCC_PATH."\"";
20778 }
20779 }
20780 }
20781 if($GSearch)
20782 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020783 if(not $CrossGcc)
20784 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020785 $GCC_PATH = get_CmdPath("gcc");
20786 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020787 if(not $GCC_PATH)
20788 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020789 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020790 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020791 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020792 { # select the latest version
20793 @GCCs = sort {$b cmp $a} @GCCs;
20794 if(check_gcc($GCCs[0], "3"))
20795 {
20796 $GCC_PATH = $GCCs[0];
20797 last;
20798 }
20799 }
20800 }
20801 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020802 if(not $GCC_PATH) {
20803 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
20804 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020805
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020806 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020807 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020808 my $GccTarget = get_dumpmachine($GCC_PATH);
20809
20810 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020811 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020812 $OStarget = "linux";
20813 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020814 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020815 elsif($GccTarget=~/symbian/)
20816 {
20817 $OStarget = "symbian";
20818 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
20819 }
20820
20821 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
20822
20823 # check GCC version
20824 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
20825 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
20826 # introduced in 4.8
20827 # fixed in 4.8.3
20828 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update or downgrade GCC or use a local installation by --gcc-path=PATH option.");
20829 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020830 }
20831 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020832 else {
20833 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020834 }
20835 }
20836 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020837 {
20838 # GCC standard paths
20839 if($GCC_PATH and not $NoStdInc)
20840 {
20841 my %DPaths = detect_inc_default_paths();
20842 @DefaultCppPaths = @{$DPaths{"Cpp"}};
20843 @DefaultGccPaths = @{$DPaths{"Gcc"}};
20844 @DefaultIncPaths = @{$DPaths{"Inc"}};
20845 push_U($SystemPaths{"include"}, @DefaultIncPaths);
20846 }
20847
20848 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020849 my $IncPath = "/usr/include";
20850 if($SystemRoot) {
20851 $IncPath = $SystemRoot.$IncPath;
20852 }
20853 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020854 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020855 }
20856 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020857
20858 if($ExtraInfo)
20859 {
20860 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
20861 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
20862 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020863}
20864
20865sub getLIB_EXT($)
20866{
20867 my $Target = $_[0];
20868 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
20869 return $Ext;
20870 }
20871 return $OS_LibExt{$LIB_TYPE}{"default"};
20872}
20873
20874sub getAR_EXT($)
20875{
20876 my $Target = $_[0];
20877 if(my $Ext = $OS_Archive{$Target}) {
20878 return $Ext;
20879 }
20880 return $OS_Archive{"default"};
20881}
20882
20883sub get_dumpversion($)
20884{
20885 my $Cmd = $_[0];
20886 return "" if(not $Cmd);
20887 if($Cache{"get_dumpversion"}{$Cmd}) {
20888 return $Cache{"get_dumpversion"}{$Cmd};
20889 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020890 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020891 chomp($V);
20892 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
20893}
20894
20895sub get_dumpmachine($)
20896{
20897 my $Cmd = $_[0];
20898 return "" if(not $Cmd);
20899 if($Cache{"get_dumpmachine"}{$Cmd}) {
20900 return $Cache{"get_dumpmachine"}{$Cmd};
20901 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020902 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020903 chomp($Machine);
20904 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
20905}
20906
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020907sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020908{
20909 my $Cmd = $_[0];
20910 return "" if(not $Cmd);
20911 my @Options = (
20912 "--version",
20913 "-help"
20914 );
20915 foreach my $Opt (@Options)
20916 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020917 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020918 if($Info) {
20919 return 1;
20920 }
20921 }
20922 return 0;
20923}
20924
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020925sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020926{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020927 my ($Cmd, $ReqVer) = @_;
20928 return 0 if(not $Cmd or not $ReqVer);
20929 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
20930 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020931 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020932 if(my $GccVer = get_dumpversion($Cmd))
20933 {
20934 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
20935 if(cmpVersions($GccVer, $ReqVer)>=0) {
20936 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
20937 }
20938 }
20939 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020940}
20941
20942sub get_depth($)
20943{
20944 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020945 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020946 }
20947 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
20948}
20949
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020950sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020951{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020952 return if($Cache{"registerGccHeaders"}); # this function should be called once
20953
20954 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020955 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020956 my @Headers = cmd_find($Path,"f");
20957 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20958 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020959 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020960 my $FileName = get_filename($HPath);
20961 if(not defined $DefaultGccHeader{$FileName})
20962 { # skip duplicated
20963 $DefaultGccHeader{$FileName} = $HPath;
20964 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020965 }
20966 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020967 $Cache{"registerGccHeaders"} = 1;
20968}
20969
20970sub registerCppHeaders()
20971{
20972 return if($Cache{"registerCppHeaders"}); # this function should be called once
20973
20974 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020975 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020976 my @Headers = cmd_find($CppDir,"f");
20977 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20978 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020979 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020980 my $FileName = get_filename($Path);
20981 if(not defined $DefaultCppHeader{$FileName})
20982 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020983 $DefaultCppHeader{$FileName} = $Path;
20984 }
20985 }
20986 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020987 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020988}
20989
20990sub parse_libname($$$)
20991{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020992 return "" if(not $_[0]);
20993 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
20994 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020995 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020996 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
20997}
20998
20999sub parse_libname_I($$$)
21000{
21001 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021002
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021003 if($Target eq "symbian") {
21004 return parse_libname_symbian($Name, $Type);
21005 }
21006 elsif($Target eq "windows") {
21007 return parse_libname_windows($Name, $Type);
21008 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021009
21010 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021011 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021012 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021013 { # libSDL-1.2.so.0.7.1
21014 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021015 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021016 if($Type eq "name")
21017 { # libSDL-1.2
21018 # libwbxml2
21019 return $2;
21020 }
21021 elsif($Type eq "name+ext")
21022 { # libSDL-1.2.so
21023 # libwbxml2.so
21024 return $1;
21025 }
21026 elsif($Type eq "version")
21027 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021028 if(defined $7
21029 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021030 { # 0.7.1
21031 return $7;
21032 }
21033 else
21034 { # libc-2.5.so (=>2.5 version)
21035 my $MV = $5;
21036 $MV=~s/\A[\-\_]+//g;
21037 return $MV;
21038 }
21039 }
21040 elsif($Type eq "short")
21041 { # libSDL
21042 # libwbxml2
21043 return $3;
21044 }
21045 elsif($Type eq "shortest")
21046 { # SDL
21047 # wbxml
21048 return shortest_name($3);
21049 }
21050 }
21051 return "";# error
21052}
21053
21054sub parse_libname_symbian($$)
21055{
21056 my ($Name, $Type) = @_;
21057 my $Ext = getLIB_EXT("symbian");
21058 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21059 { # libpthread{00010001}.dso
21060 if($Type eq "name")
21061 { # libpthread{00010001}
21062 return $2;
21063 }
21064 elsif($Type eq "name+ext")
21065 { # libpthread{00010001}.dso
21066 return $1;
21067 }
21068 elsif($Type eq "version")
21069 { # 00010001
21070 my $V = $4;
21071 $V=~s/\{(.+)\}/$1/;
21072 return $V;
21073 }
21074 elsif($Type eq "short")
21075 { # libpthread
21076 return $3;
21077 }
21078 elsif($Type eq "shortest")
21079 { # pthread
21080 return shortest_name($3);
21081 }
21082 }
21083 return "";# error
21084}
21085
21086sub parse_libname_windows($$)
21087{
21088 my ($Name, $Type) = @_;
21089 my $Ext = getLIB_EXT("windows");
21090 if($Name=~/((.+?)\.$Ext)\Z/)
21091 { # netapi32.dll
21092 if($Type eq "name")
21093 { # netapi32
21094 return $2;
21095 }
21096 elsif($Type eq "name+ext")
21097 { # netapi32.dll
21098 return $1;
21099 }
21100 elsif($Type eq "version")
21101 { # DLL version embedded
21102 # at binary-level
21103 return "";
21104 }
21105 elsif($Type eq "short")
21106 { # netapi32
21107 return $2;
21108 }
21109 elsif($Type eq "shortest")
21110 { # netapi
21111 return shortest_name($2);
21112 }
21113 }
21114 return "";# error
21115}
21116
21117sub shortest_name($)
21118{
21119 my $Name = $_[0];
21120 # remove prefix
21121 $Name=~s/\A(lib|open)//;
21122 # remove suffix
21123 $Name=~s/[\W\d_]+\Z//i;
21124 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21125 return $Name;
21126}
21127
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021128sub createSymbolsList($$$$$)
21129{
21130 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021131
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021132 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021133 prepareSymbols(1);
21134
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021135 my %SymbolHeaderLib = ();
21136 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021137
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021138 # Get List
21139 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21140 {
21141 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021142 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021143 next;
21144 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021145 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021146 { # skip other symbols
21147 next;
21148 }
21149 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21150 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021151 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021152 next;
21153 }
21154 my $DyLib = $Symbol_Library{1}{$Symbol};
21155 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021156 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021157 next;
21158 }
21159 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21160 $Total+=1;
21161 }
21162 # Draw List
21163 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21164 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21165 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21166 {
21167 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21168 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021169 my %NS_Symbol = ();
21170 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021171 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021172 }
21173 foreach my $NameSpace (sort keys(%NS_Symbol))
21174 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021175 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021176 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21177 foreach my $Symbol (@SortedInterfaces)
21178 {
21179 my $SubReport = "";
21180 my $Signature = get_Signature($Symbol, 1);
21181 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021182 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021183 }
21184 if($Symbol=~/\A(_Z|\?)/)
21185 {
21186 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021187 $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 +040021188 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021189 else {
21190 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21191 }
21192 }
21193 else
21194 {
21195 if($Signature) {
21196 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21197 }
21198 else {
21199 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21200 }
21201 }
21202 $SYMBOLS_LIST .= $SubReport;
21203 }
21204 }
21205 $SYMBOLS_LIST .= "<br/>\n";
21206 }
21207 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021208 # clear info
21209 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21210 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21211 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21212 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021213 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021214 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021215 my $CssStyles = readModule("Styles", "SymbolsList.css");
21216 my $JScripts = readModule("Scripts", "Sections.js");
21217 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021218 my $Title = "$LName: public symbols";
21219 my $Keywords = "$LName, API, symbols";
21220 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021221 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021222 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021223 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021224 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021225 writeFile($SaveTo, $SYMBOLS_LIST);
21226}
21227
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021228sub add_target_libs($)
21229{
21230 foreach (@{$_[0]}) {
21231 $TargetLibs{$_} = 1;
21232 }
21233}
21234
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021235sub is_target_lib($)
21236{
21237 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021238 if(not $LName) {
21239 return 0;
21240 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021241 if($TargetLibraryName
21242 and $LName!~/\Q$TargetLibraryName\E/) {
21243 return 0;
21244 }
21245 if(keys(%TargetLibs)
21246 and not $TargetLibs{$LName}
21247 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21248 return 0;
21249 }
21250 return 1;
21251}
21252
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021253sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021254{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021255 my ($H, $V) = @_;
21256 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021257 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021258 if($TargetHeaders{$V}{$H}) {
21259 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021260 }
21261 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021262 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021263}
21264
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021265sub readLibs($)
21266{
21267 my $LibVersion = $_[0];
21268 if($OStarget eq "windows")
21269 { # dumpbin.exe will crash
21270 # without VS Environment
21271 check_win32_env();
21272 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021273 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021274 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021275 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021276}
21277
21278sub dump_sorting($)
21279{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021280 my $Hash = $_[0];
21281 return [] if(not $Hash);
21282 my @Keys = keys(%{$Hash});
21283 return [] if($#Keys<0);
21284 if($Keys[0]=~/\A\d+\Z/)
21285 { # numbers
21286 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021287 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021288 else
21289 { # strings
21290 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021291 }
21292}
21293
21294sub printMsg($$)
21295{
21296 my ($Type, $Msg) = @_;
21297 if($Type!~/\AINFO/) {
21298 $Msg = $Type.": ".$Msg;
21299 }
21300 if($Type!~/_C\Z/) {
21301 $Msg .= "\n";
21302 }
21303 if($Quiet)
21304 { # --quiet option
21305 appendFile($COMMON_LOG_PATH, $Msg);
21306 }
21307 else
21308 {
21309 if($Type eq "ERROR") {
21310 print STDERR $Msg;
21311 }
21312 else {
21313 print $Msg;
21314 }
21315 }
21316}
21317
21318sub exitStatus($$)
21319{
21320 my ($Code, $Msg) = @_;
21321 printMsg("ERROR", $Msg);
21322 exit($ERROR_CODE{$Code});
21323}
21324
21325sub exitReport()
21326{ # the tool has run without any errors
21327 printReport();
21328 if($COMPILE_ERRORS)
21329 { # errors in headers may add false positives/negatives
21330 exit($ERROR_CODE{"Compile_Error"});
21331 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021332 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21333 { # --binary
21334 exit($ERROR_CODE{"Incompatible"});
21335 }
21336 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21337 { # --source
21338 exit($ERROR_CODE{"Incompatible"});
21339 }
21340 elsif($RESULT{"Source"}{"Problems"}
21341 or $RESULT{"Binary"}{"Problems"})
21342 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021343 exit($ERROR_CODE{"Incompatible"});
21344 }
21345 else {
21346 exit($ERROR_CODE{"Compatible"});
21347 }
21348}
21349
21350sub readRules($)
21351{
21352 my $Kind = $_[0];
21353 if(not -f $RULES_PATH{$Kind}) {
21354 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21355 }
21356 my $Content = readFile($RULES_PATH{$Kind});
21357 while(my $Rule = parseTag(\$Content, "rule"))
21358 {
21359 my $RId = parseTag(\$Rule, "id");
21360 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21361 foreach my $Prop (@Properties) {
21362 if(my $Value = parseTag(\$Rule, lc($Prop)))
21363 {
21364 $Value=~s/\n[ ]*//;
21365 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21366 }
21367 }
21368 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21369 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21370 }
21371 else {
21372 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21373 }
21374 }
21375}
21376
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021377sub getReportPath($)
21378{
21379 my $Level = $_[0];
21380 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21381 if($Level eq "Binary")
21382 {
21383 if($BinaryReportPath)
21384 { # --bin-report-path
21385 return $BinaryReportPath;
21386 }
21387 elsif($OutputReportPath)
21388 { # --report-path
21389 return $OutputReportPath;
21390 }
21391 else
21392 { # default
21393 return $Dir."/abi_compat_report.$ReportFormat";
21394 }
21395 }
21396 elsif($Level eq "Source")
21397 {
21398 if($SourceReportPath)
21399 { # --src-report-path
21400 return $SourceReportPath;
21401 }
21402 elsif($OutputReportPath)
21403 { # --report-path
21404 return $OutputReportPath;
21405 }
21406 else
21407 { # default
21408 return $Dir."/src_compat_report.$ReportFormat";
21409 }
21410 }
21411 else
21412 {
21413 if($OutputReportPath)
21414 { # --report-path
21415 return $OutputReportPath;
21416 }
21417 else
21418 { # default
21419 return $Dir."/compat_report.$ReportFormat";
21420 }
21421 }
21422}
21423
21424sub printStatMsg($)
21425{
21426 my $Level = $_[0];
21427 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21428}
21429
21430sub listAffected($)
21431{
21432 my $Level = $_[0];
21433 my $List = "";
21434 foreach (keys(%{$TotalAffected{$Level}}))
21435 {
21436 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21437 { # skip "Low"-severity problems
21438 next;
21439 }
21440 $List .= "$_\n";
21441 }
21442 my $Dir = get_dirname(getReportPath($Level));
21443 if($Level eq "Binary") {
21444 writeFile($Dir."/abi_affected.txt", $List);
21445 }
21446 elsif($Level eq "Source") {
21447 writeFile($Dir."/src_affected.txt", $List);
21448 }
21449}
21450
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021451sub printReport()
21452{
21453 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021454 createReport();
21455 if($JoinReport or $DoubleReport)
21456 {
21457 if($RESULT{"Binary"}{"Problems"}
21458 or $RESULT{"Source"}{"Problems"}) {
21459 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021460 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021461 else {
21462 printMsg("INFO", "result: COMPATIBLE");
21463 }
21464 printStatMsg("Binary");
21465 printStatMsg("Source");
21466 if($ListAffected)
21467 { # --list-affected
21468 listAffected("Binary");
21469 listAffected("Source");
21470 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021471 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021472 elsif($BinaryOnly)
21473 {
21474 if($RESULT{"Binary"}{"Problems"}) {
21475 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21476 }
21477 else {
21478 printMsg("INFO", "result: COMPATIBLE");
21479 }
21480 printStatMsg("Binary");
21481 if($ListAffected)
21482 { # --list-affected
21483 listAffected("Binary");
21484 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021485 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021486 elsif($SourceOnly)
21487 {
21488 if($RESULT{"Source"}{"Problems"}) {
21489 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21490 }
21491 else {
21492 printMsg("INFO", "result: COMPATIBLE");
21493 }
21494 printStatMsg("Source");
21495 if($ListAffected)
21496 { # --list-affected
21497 listAffected("Source");
21498 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021499 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021500 if($StdOut)
21501 {
21502 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021503 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021504 printMsg("INFO", "compatibility report has been generated to stdout");
21505 }
21506 else
21507 { # default
21508 printMsg("INFO", "compatibility reports have been generated to stdout");
21509 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021510 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021511 else
21512 {
21513 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021514 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021515 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21516 }
21517 elsif($DoubleReport)
21518 { # default
21519 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21520 }
21521 elsif($BinaryOnly)
21522 { # --binary
21523 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21524 }
21525 elsif($SourceOnly)
21526 { # --source
21527 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21528 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021529 }
21530}
21531
21532sub check_win32_env()
21533{
21534 if(not $ENV{"DevEnvDir"}
21535 or not $ENV{"LIB"}) {
21536 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21537 }
21538}
21539
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021540sub diffSets($$)
21541{
21542 my ($S1, $S2) = @_;
21543 my @SK1 = keys(%{$S1});
21544 my @SK2 = keys(%{$S2});
21545 if($#SK1!=$#SK2) {
21546 return 1;
21547 }
21548 foreach my $K1 (@SK1)
21549 {
21550 if(not defined $S2->{$K1}) {
21551 return 1;
21552 }
21553 }
21554 return 0;
21555}
21556
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021557sub defaultDumpPath($$)
21558{
21559 my ($N, $V) = @_;
21560 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21561}
21562
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021563sub create_ABI_Dump()
21564{
21565 if(not -e $DumpAPI) {
21566 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21567 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021568
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021569 if(isDump($DumpAPI)) {
21570 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021571 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021572 else {
21573 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021574 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021575
21576 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021577 { # set to default: N
21578 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021579 }
21580
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021581 initLogging(1);
21582 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021583
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021584 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021585 if($OutputDumpPath)
21586 { # user defined path
21587 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021588 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021589 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21590
21591 if(not $Archive and not $StdOut)
21592 { # check archive utilities
21593 if($OSgroup eq "windows")
21594 { # using zip
21595 my $ZipCmd = get_CmdPath("zip");
21596 if(not $ZipCmd) {
21597 exitStatus("Not_Found", "can't find \"zip\"");
21598 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021599 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021600 else
21601 { # using tar and gzip
21602 my $TarCmd = get_CmdPath("tar");
21603 if(not $TarCmd) {
21604 exitStatus("Not_Found", "can't find \"tar\"");
21605 }
21606 my $GzipCmd = get_CmdPath("gzip");
21607 if(not $GzipCmd) {
21608 exitStatus("Not_Found", "can't find \"gzip\"");
21609 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021610 }
21611 }
21612
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021613 if(not $Descriptor{1}{"Dump"})
21614 {
21615 if(not $CheckHeadersOnly) {
21616 readLibs(1);
21617 }
21618 if($CheckHeadersOnly) {
21619 setLanguage(1, "C++");
21620 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021621 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021622 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021623 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021624 if(not $Descriptor{1}{"Dump"})
21625 {
21626 if($Descriptor{1}{"Headers"}) {
21627 readHeaders(1);
21628 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021629 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021630 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021631 if(not keys(%{$SymbolInfo{1}}))
21632 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021633 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021634 {
21635 if($CheckHeadersOnly) {
21636 exitStatus("Empty_Set", "the set of public symbols is empty");
21637 }
21638 else {
21639 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21640 }
21641 }
21642 }
21643 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021644 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021645 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21646 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021647 if($ExtraDump)
21648 { # add unmangled names to the ABI dump
21649 my @Names = ();
21650 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21651 {
21652 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21653 push(@Names, $MnglName);
21654 }
21655 }
21656 translateSymbols(@Names, 1);
21657 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21658 {
21659 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21660 {
21661 if(my $Unmangled = $tr_name{$MnglName})
21662 {
21663 if($MnglName ne $Unmangled) {
21664 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21665 }
21666 }
21667 }
21668 }
21669 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021670
21671 my %GccConstants = (); # built-in GCC constants
21672 foreach my $Name (keys(%{$Constants{1}}))
21673 {
21674 if(not defined $Constants{1}{$Name}{"Header"})
21675 {
21676 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21677 delete($Constants{1}{$Name});
21678 }
21679 }
21680
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021681 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021682 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021683 "TypeInfo" => $TypeInfo{1},
21684 "SymbolInfo" => $SymbolInfo{1},
21685 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021686 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021687 "SymbolVersion" => $SymVer{1},
21688 "LibraryVersion" => $Descriptor{1}{"Version"},
21689 "LibraryName" => $TargetLibraryName,
21690 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021691 "SkipTypes" => $SkipTypes{1},
21692 "SkipSymbols" => $SkipSymbols{1},
21693 "SkipNameSpaces" => $SkipNameSpaces{1},
21694 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021695 "Headers" => \%HeadersInfo,
21696 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021697 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021698 "NameSpaces" => $NestedNameSpaces{1},
21699 "Target" => $OStarget,
21700 "Arch" => getArch(1),
21701 "WordSize" => $WORD_SIZE{1},
21702 "GccVersion" => get_dumpversion($GCC_PATH),
21703 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21704 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21705 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021706 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021707 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021708 }
21709 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021710 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021711 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021712 if($ExtendedCheck)
21713 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021714 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021715 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021716 if($BinaryOnly)
21717 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021718 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021719 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021720 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021721 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021722 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021723 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21724 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021725 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021726
21727 my $ABI_DUMP = "";
21728 if($UseXML)
21729 {
21730 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021731 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021732 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021733 else
21734 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021735 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021736 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021737 if($StdOut)
21738 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021739 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021740 printMsg("INFO", "ABI dump has been generated to stdout");
21741 return;
21742 }
21743 else
21744 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021745 my ($DDir, $DName) = separate_path($DumpPath);
21746 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021747 if(not $Archive) {
21748 $DPath = $DumpPath;
21749 }
21750
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021751 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021752
21753 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021754 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021755 close(DUMP);
21756
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021757 if(not -s $DPath) {
21758 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21759 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021760 if($Archive) {
21761 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021762 }
21763
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021764 if($OutputDumpPath) {
21765 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021766 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021767 else {
21768 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
21769 }
21770 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 +040021771 }
21772}
21773
21774sub quickEmptyReports()
21775{ # Quick "empty" reports
21776 # 4 times faster than merging equal dumps
21777 # NOTE: the dump contains the "LibraryVersion" attribute
21778 # if you change the version, then your dump will be different
21779 # OVERCOME: use -v1 and v2 options for comparing dumps
21780 # and don't change version in the XML descriptor (and dumps)
21781 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
21782 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
21783 {
21784 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
21785 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
21786 if($FilePath1 and $FilePath2)
21787 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021788 my $Line = readLineNum($FilePath1, 0);
21789 if($Line=~/xml/)
21790 { # XML format
21791 # is not supported yet
21792 return;
21793 }
21794
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021795 local $/ = undef;
21796
21797 open(DUMP1, $FilePath1);
21798 my $Content1 = <DUMP1>;
21799 close(DUMP1);
21800
21801 open(DUMP2, $FilePath2);
21802 my $Content2 = <DUMP2>;
21803 close(DUMP2);
21804
21805 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021806 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021807 # clean memory
21808 undef $Content2;
21809
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021810 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021811 my $ABIdump = eval($Content1);
21812
21813 # clean memory
21814 undef $Content1;
21815
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021816 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021817 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 +040021818 }
21819 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021820 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021821 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
21822 }
21823 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021824 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021825 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
21826 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021827 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021828 read_Libs_DumpInfo($ABIdump, 1);
21829 read_Machine_DumpInfo($ABIdump, 1);
21830 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021831
21832 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
21833 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
21834
21835 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
21836 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
21837
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021838 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
21839 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
21840 exitReport();
21841 }
21842 }
21843 }
21844}
21845
21846sub initLogging($)
21847{
21848 my $LibVersion = $_[0];
21849 # create log directory
21850 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
21851 if($OutputLogPath{$LibVersion})
21852 { # user-defined by -log-path option
21853 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
21854 }
21855 if($LogMode ne "n") {
21856 mkpath($LOG_DIR);
21857 }
21858 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021859 if($Debug)
21860 { # debug directory
21861 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021862
21863 if(not $ExtraInfo)
21864 { # enable --extra-info
21865 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
21866 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021867 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021868 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021869}
21870
21871sub writeLog($$)
21872{
21873 my ($LibVersion, $Msg) = @_;
21874 if($LogMode ne "n") {
21875 appendFile($LOG_PATH{$LibVersion}, $Msg);
21876 }
21877}
21878
21879sub resetLogging($)
21880{
21881 my $LibVersion = $_[0];
21882 if($LogMode!~/a|n/)
21883 { # remove old log
21884 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021885 if($Debug) {
21886 rmtree($DEBUG_PATH{$LibVersion});
21887 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021888 }
21889}
21890
21891sub printErrorLog($)
21892{
21893 my $LibVersion = $_[0];
21894 if($LogMode ne "n") {
21895 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
21896 }
21897}
21898
21899sub isDump($)
21900{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021901 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
21902 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021903 return $1;
21904 }
21905 return 0;
21906}
21907
21908sub isDump_U($)
21909{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021910 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021911 return $1;
21912 }
21913 return 0;
21914}
21915
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021916sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021917{
21918 # read input XML descriptors or ABI dumps
21919 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021920 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021921 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021922 if(not -e $Descriptor{1}{"Path"}) {
21923 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021924 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021925
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021926 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021927 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021928 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021929 if(not -e $Descriptor{2}{"Path"}) {
21930 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021931 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021932
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021933 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021934 if(isDump($Descriptor{1}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021935 and isDump($Descriptor{2}{"Path"}))
21936 { # optimization: equal ABI dumps
21937 quickEmptyReports();
21938 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021939
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021940 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021941
21942 if(isDump($Descriptor{1}{"Path"})) {
21943 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021944 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021945 else {
21946 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
21947 }
21948
21949 if(isDump($Descriptor{2}{"Path"})) {
21950 read_ABI_Dump(2, $Descriptor{2}{"Path"});
21951 }
21952 else {
21953 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021954 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021955
21956 if(not $Descriptor{1}{"Version"})
21957 { # set to default: X
21958 $Descriptor{1}{"Version"} = "X";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030021959 print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021960 }
21961
21962 if(not $Descriptor{2}{"Version"})
21963 { # set to default: Y
21964 $Descriptor{2}{"Version"} = "Y";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030021965 print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021966 }
21967
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030021968 if(not $UsedDump{1}{"V"}) {
21969 initLogging(1);
21970 }
21971
21972 if(not $UsedDump{2}{"V"}) {
21973 initLogging(2);
21974 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021975
21976 # check input data
21977 if(not $Descriptor{1}{"Headers"}) {
21978 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021979 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021980 if(not $Descriptor{2}{"Headers"}) {
21981 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021982 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021983
21984 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021985 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021986 if(not $Descriptor{1}{"Libs"}) {
21987 exitStatus("Error", "can't find libraries info in descriptor d1");
21988 }
21989 if(not $Descriptor{2}{"Libs"}) {
21990 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021991 }
21992 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021993
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021994 if($UseDumps)
21995 { # --use-dumps
21996 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021997 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
21998 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021999
22000 unlink($DumpPath1);
22001 unlink($DumpPath2);
22002
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022003 my $pid = fork();
22004 if($pid)
22005 { # dump on two CPU cores
22006 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22007 if($RelativeDirectory{1}) {
22008 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22009 }
22010 if($OutputLogPath{1}) {
22011 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22012 }
22013 if($CrossGcc) {
22014 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22015 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022016 if($Quiet)
22017 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022018 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022019 @PARAMS = (@PARAMS, "-logging-mode", "a");
22020 }
22021 elsif($LogMode and $LogMode ne "w")
22022 { # "w" is default
22023 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022024 }
22025 if($ExtendedCheck) {
22026 @PARAMS = (@PARAMS, "-extended");
22027 }
22028 if($UserLang) {
22029 @PARAMS = (@PARAMS, "-lang", $UserLang);
22030 }
22031 if($TargetVersion{1}) {
22032 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22033 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022034 if($BinaryOnly) {
22035 @PARAMS = (@PARAMS, "-binary");
22036 }
22037 if($SourceOnly) {
22038 @PARAMS = (@PARAMS, "-source");
22039 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022040 if($SortDump) {
22041 @PARAMS = (@PARAMS, "-sort");
22042 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022043 if($DumpFormat and $DumpFormat ne "perl") {
22044 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22045 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022046 if($CheckHeadersOnly) {
22047 @PARAMS = (@PARAMS, "-headers-only");
22048 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022049 if($Debug)
22050 {
22051 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022052 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022053 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022054 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022055 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022056 exit(1);
22057 }
22058 }
22059 else
22060 { # child
22061 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22062 if($RelativeDirectory{2}) {
22063 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22064 }
22065 if($OutputLogPath{2}) {
22066 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22067 }
22068 if($CrossGcc) {
22069 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22070 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022071 if($Quiet)
22072 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022073 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022074 @PARAMS = (@PARAMS, "-logging-mode", "a");
22075 }
22076 elsif($LogMode and $LogMode ne "w")
22077 { # "w" is default
22078 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022079 }
22080 if($ExtendedCheck) {
22081 @PARAMS = (@PARAMS, "-extended");
22082 }
22083 if($UserLang) {
22084 @PARAMS = (@PARAMS, "-lang", $UserLang);
22085 }
22086 if($TargetVersion{2}) {
22087 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22088 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022089 if($BinaryOnly) {
22090 @PARAMS = (@PARAMS, "-binary");
22091 }
22092 if($SourceOnly) {
22093 @PARAMS = (@PARAMS, "-source");
22094 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022095 if($SortDump) {
22096 @PARAMS = (@PARAMS, "-sort");
22097 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022098 if($DumpFormat and $DumpFormat ne "perl") {
22099 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22100 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022101 if($CheckHeadersOnly) {
22102 @PARAMS = (@PARAMS, "-headers-only");
22103 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022104 if($Debug)
22105 {
22106 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022107 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022108 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022109 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022110 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022111 exit(1);
22112 }
22113 else {
22114 exit(0);
22115 }
22116 }
22117 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022118
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022119 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022120 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22121 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022122 if($TargetTitle ne $TargetLibraryName) {
22123 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022124 }
22125 if($ShowRetVal) {
22126 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22127 }
22128 if($CrossGcc) {
22129 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22130 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022131 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22132 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022133 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022134 }
22135 if($ReportFormat and $ReportFormat ne "html")
22136 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022137 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22138 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022139 if($OutputReportPath) {
22140 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22141 }
22142 if($BinaryReportPath) {
22143 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22144 }
22145 if($SourceReportPath) {
22146 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22147 }
22148 if($LoggingPath) {
22149 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22150 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022151 if($CheckHeadersOnly) {
22152 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22153 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022154 if($BinaryOnly) {
22155 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22156 }
22157 if($SourceOnly) {
22158 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22159 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022160 if($Debug)
22161 {
22162 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22163 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022164 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022165 system("perl", $0, @CMP_PARAMS);
22166 exit($?>>8);
22167 }
22168 if(not $Descriptor{1}{"Dump"}
22169 or not $Descriptor{2}{"Dump"})
22170 { # need GCC toolchain to analyze
22171 # header files and libraries
22172 detect_default_paths("inc|lib|gcc");
22173 }
22174 if(not $Descriptor{1}{"Dump"})
22175 {
22176 if(not $CheckHeadersOnly) {
22177 readLibs(1);
22178 }
22179 if($CheckHeadersOnly) {
22180 setLanguage(1, "C++");
22181 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022182 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022183 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022184 }
22185 if(not $Descriptor{2}{"Dump"})
22186 {
22187 if(not $CheckHeadersOnly) {
22188 readLibs(2);
22189 }
22190 if($CheckHeadersOnly) {
22191 setLanguage(2, "C++");
22192 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022193 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022194 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022195 }
22196 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22197 { # support for old ABI dumps
22198 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022199 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022200 {
22201 $WORD_SIZE{1} = $WORD_SIZE{2};
22202 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22203 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022204 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022205 {
22206 $WORD_SIZE{2} = $WORD_SIZE{1};
22207 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22208 }
22209 }
22210 elsif(not $WORD_SIZE{1}
22211 and not $WORD_SIZE{2})
22212 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022213 $WORD_SIZE{1} = "4";
22214 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022215 }
22216 if($Descriptor{1}{"Dump"})
22217 { # support for old ABI dumps
22218 prepareTypes(1);
22219 }
22220 if($Descriptor{2}{"Dump"})
22221 { # support for old ABI dumps
22222 prepareTypes(2);
22223 }
22224 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22225 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22226 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022227 # process input data
22228 if($Descriptor{1}{"Headers"}
22229 and not $Descriptor{1}{"Dump"}) {
22230 readHeaders(1);
22231 }
22232 if($Descriptor{2}{"Headers"}
22233 and not $Descriptor{2}{"Dump"}) {
22234 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022235 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022236
22237 # clean memory
22238 %SystemHeaders = ();
22239 %mangled_name_gcc = ();
22240
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022241 prepareSymbols(1);
22242 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022243
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022244 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022245 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022246
22247 # Virtual Tables
22248 registerVTable(1);
22249 registerVTable(2);
22250
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022251 if(not checkDump(1, "1.22")
22252 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022253 { # support for old ABI dumps
22254 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22255 {
22256 if($ClassName=~/</)
22257 { # templates
22258 if(not defined $VirtualTable{1}{$ClassName})
22259 { # synchronize
22260 delete($VirtualTable{2}{$ClassName});
22261 }
22262 }
22263 }
22264 }
22265
22266 registerOverriding(1);
22267 registerOverriding(2);
22268
22269 setVirtFuncPositions(1);
22270 setVirtFuncPositions(2);
22271
22272 # Other
22273 addParamNames(1);
22274 addParamNames(2);
22275
22276 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022277}
22278
22279sub compareAPIs($)
22280{
22281 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022282
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022283 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022284 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022285
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022286 if($Level eq "Binary") {
22287 printMsg("INFO", "comparing ABIs ...");
22288 }
22289 else {
22290 printMsg("INFO", "comparing APIs ...");
22291 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022292
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022293 if($CheckHeadersOnly
22294 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022295 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022296 detectAdded_H($Level);
22297 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022298 }
22299 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022300 { # added/removed in libs
22301 detectAdded($Level);
22302 detectRemoved($Level);
22303 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022304
22305 mergeSymbols($Level);
22306 if(keys(%{$CheckedSymbols{$Level}})) {
22307 mergeConstants($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022308 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022309
22310 $Cache{"mergeTypes"} = (); # free memory
22311
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022312 if($CheckHeadersOnly
22313 or $Level eq "Source")
22314 { # added/removed in headers
22315 mergeHeaders($Level);
22316 }
22317 else
22318 { # added/removed in libs
22319 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022320 }
22321}
22322
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022323sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022324{
22325 my %Opts = (
22326 "OStarget"=>$OStarget,
22327 "Debug"=>$Debug,
22328 "Quiet"=>$Quiet,
22329 "LogMode"=>$LogMode,
22330 "CheckHeadersOnly"=>$CheckHeadersOnly,
22331
22332 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022333 "GCC_PATH"=>$GCC_PATH,
22334 "TargetSysInfo"=>$TargetSysInfo,
22335 "CrossPrefix"=>$CrossPrefix,
22336 "TargetLibraryName"=>$TargetLibraryName,
22337 "CrossGcc"=>$CrossGcc,
22338 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022339 "NoStdInc"=>$NoStdInc,
22340
22341 "BinaryOnly" => $BinaryOnly,
22342 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022343 );
22344 return \%Opts;
22345}
22346
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022347sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022348{
22349 my %CODE_ERROR = reverse(%ERROR_CODE);
22350 return $CODE_ERROR{$_[0]};
22351}
22352
22353sub scenario()
22354{
22355 if($StdOut)
22356 { # enable quiet mode
22357 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022358 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022359 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022360 if(not $LogMode)
22361 { # default
22362 $LogMode = "w";
22363 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022364 if($UserLang)
22365 { # --lang=C++
22366 $UserLang = uc($UserLang);
22367 $COMMON_LANGUAGE{1}=$UserLang;
22368 $COMMON_LANGUAGE{2}=$UserLang;
22369 }
22370 if($LoggingPath)
22371 {
22372 $OutputLogPath{1} = $LoggingPath;
22373 $OutputLogPath{2} = $LoggingPath;
22374 if($Quiet) {
22375 $COMMON_LOG_PATH = $LoggingPath;
22376 }
22377 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022378
22379 if($SkipInternalSymbols) {
22380 $SkipInternalSymbols=~s/\*/.*/g;
22381 }
22382
22383 if($SkipInternalTypes) {
22384 $SkipInternalTypes=~s/\*/.*/g;
22385 }
22386
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022387 if($Quick) {
22388 $ADD_TMPL_INSTANCES = 0;
22389 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022390 if($OutputDumpPath)
22391 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022392 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022393 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22394 }
22395 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022396 if($BinaryOnly and $SourceOnly)
22397 { # both --binary and --source
22398 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022399 if(not $CmpSystems)
22400 {
22401 $BinaryOnly = 0;
22402 $SourceOnly = 0;
22403 }
22404
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022405 $DoubleReport = 1;
22406 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022407
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022408 if($OutputReportPath)
22409 { # --report-path
22410 $DoubleReport = 0;
22411 $JoinReport = 1;
22412 }
22413 }
22414 elsif($BinaryOnly or $SourceOnly)
22415 { # --binary or --source
22416 $DoubleReport = 0;
22417 $JoinReport = 0;
22418 }
22419 if($UseXML)
22420 { # --xml option
22421 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022422 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022423 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022424 if($ReportFormat)
22425 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022426 $ReportFormat = lc($ReportFormat);
22427 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022428 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022429 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022430 if($ReportFormat eq "htm")
22431 { # HTM == HTML
22432 $ReportFormat = "html";
22433 }
22434 elsif($ReportFormat eq "xml")
22435 { # --report-format=XML equal to --xml
22436 $UseXML = 1;
22437 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022438 }
22439 else
22440 { # default: HTML
22441 $ReportFormat = "html";
22442 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022443 if($DumpFormat)
22444 { # validate
22445 $DumpFormat = lc($DumpFormat);
22446 if($DumpFormat!~/\A(xml|perl)\Z/) {
22447 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22448 }
22449 if($DumpFormat eq "xml")
22450 { # --dump-format=XML equal to --xml
22451 $UseXML = 1;
22452 }
22453 }
22454 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022455 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022456 $DumpFormat = "perl";
22457 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022458 if($Quiet and $LogMode!~/a|n/)
22459 { # --quiet log
22460 if(-f $COMMON_LOG_PATH) {
22461 unlink($COMMON_LOG_PATH);
22462 }
22463 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022464 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022465 $CheckUndefined = 1;
22466 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022467 if($TestTool and $UseDumps)
22468 { # --test && --use-dumps == --test-dump
22469 $TestDump = 1;
22470 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022471 if($Tolerant)
22472 { # enable all
22473 $Tolerance = 1234;
22474 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022475 if($Help)
22476 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022477 HELP_MESSAGE();
22478 exit(0);
22479 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022480 if($InfoMsg)
22481 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022482 INFO_MESSAGE();
22483 exit(0);
22484 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022485 if($ShowVersion)
22486 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022487 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 +040022488 exit(0);
22489 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022490 if($DumpVersion)
22491 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022492 printMsg("INFO", $TOOL_VERSION);
22493 exit(0);
22494 }
22495 if($ExtendedCheck) {
22496 $CheckHeadersOnly = 1;
22497 }
22498 if($SystemRoot_Opt)
22499 { # user defined root
22500 if(not -e $SystemRoot_Opt) {
22501 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22502 }
22503 $SystemRoot = $SystemRoot_Opt;
22504 $SystemRoot=~s/[\/]+\Z//g;
22505 if($SystemRoot) {
22506 $SystemRoot = get_abs_path($SystemRoot);
22507 }
22508 }
22509 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022510
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022511 if($SortDump)
22512 {
22513 $Data::Dumper::Useperl = 1;
22514 $Data::Dumper::Sortkeys = \&dump_sorting;
22515 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022516
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022517 if($TargetLibsPath)
22518 {
22519 if(not -f $TargetLibsPath) {
22520 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22521 }
22522 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22523 $TargetLibs{$Lib} = 1;
22524 }
22525 }
22526 if($TargetHeadersPath)
22527 { # --headers-list
22528 if(not -f $TargetHeadersPath) {
22529 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22530 }
22531 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22532 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022533 $TargetHeaders{1}{get_filename($Header)} = 1;
22534 $TargetHeaders{2}{get_filename($Header)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022535 }
22536 }
22537 if($TargetHeader)
22538 { # --header
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022539 $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
22540 $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022541 }
22542 if($TestTool
22543 or $TestDump)
22544 { # --test, --test-dump
22545 detect_default_paths("bin|gcc"); # to compile libs
22546 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022547 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022548 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022549 exit(0);
22550 }
22551 if($DumpSystem)
22552 { # --dump-system
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022553
22554 if(not $TargetSysInfo) {
22555 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22556 }
22557
22558 if(not -d $TargetSysInfo) {
22559 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22560 }
22561
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022562 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022563 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022564 { # system XML descriptor
22565 if(not -f $DumpSystem) {
22566 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22567 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030022568
22569 my $SDesc = readFile($DumpSystem);
22570 if(my $RelDir = $RelativeDirectory{1}) {
22571 $SDesc =~ s/{RELPATH}/$RelDir/g;
22572 }
22573
22574 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022575 foreach (@{$Ret->{"Tools"}})
22576 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022577 push_U($SystemPaths{"bin"}, $_);
22578 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022579 }
22580 if($Ret->{"CrossPrefix"}) {
22581 $CrossPrefix = $Ret->{"CrossPrefix"};
22582 }
22583 }
22584 elsif($SystemRoot_Opt)
22585 { # -sysroot "/" option
22586 # default target: /usr/lib, /usr/include
22587 # search libs: /usr/lib and /lib
22588 if(not -e $SystemRoot."/usr/lib") {
22589 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22590 }
22591 if(not -e $SystemRoot."/lib") {
22592 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22593 }
22594 if(not -e $SystemRoot."/usr/include") {
22595 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22596 }
22597 readSystemDescriptor("
22598 <name>
22599 $DumpSystem
22600 </name>
22601 <headers>
22602 $SystemRoot/usr/include
22603 </headers>
22604 <libs>
22605 $SystemRoot/usr/lib
22606 </libs>
22607 <search_libs>
22608 $SystemRoot/lib
22609 </search_libs>");
22610 }
22611 else {
22612 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22613 }
22614 detect_default_paths("bin|gcc"); # to check symbols
22615 if($OStarget eq "windows")
22616 { # to run dumpbin.exe
22617 # and undname.exe
22618 check_win32_env();
22619 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022620 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022621 exit(0);
22622 }
22623 if($CmpSystems)
22624 { # --cmp-systems
22625 detect_default_paths("bin"); # to extract dumps
22626 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022627 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022628 exit(0);
22629 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022630 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022631 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022632 }
22633 else
22634 { # validate library name
22635 if($TargetLibraryName=~/[\*\/\\]/) {
22636 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22637 }
22638 }
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022639 if(not $TargetTitle) {
22640 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022641 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022642
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022643 if($SymbolsListPath)
22644 {
22645 if(not -f $SymbolsListPath) {
22646 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22647 }
22648 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22649 $SymbolsList{$Interface} = 1;
22650 }
22651 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022652 if($TypesListPath)
22653 {
22654 if(not -f $TypesListPath) {
22655 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
22656 }
22657 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
22658 $TypesList{$Type} = 1;
22659 }
22660 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022661 if($SkipSymbolsListPath)
22662 {
22663 if(not -f $SkipSymbolsListPath) {
22664 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22665 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030022666 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
22667 {
22668 $SkipSymbols{1}{$Interface} = 1;
22669 $SkipSymbols{2}{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022670 }
22671 }
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030022672 if($SkipTypesListPath)
22673 {
22674 if(not -f $SkipTypesListPath) {
22675 exitStatus("Access_Error", "can't access file \'$SkipTypesListPath\'");
22676 }
22677 foreach my $Type (split(/\s*\n\s*/, readFile($SkipTypesListPath)))
22678 {
22679 $SkipTypes{1}{$Type} = 1;
22680 $SkipTypes{2}{$Type} = 1;
22681 }
22682 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022683 if($SkipHeadersPath)
22684 {
22685 if(not -f $SkipHeadersPath) {
22686 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22687 }
22688 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022689 { # register for both versions
22690 $SkipHeadersList{1}{$Path} = 1;
22691 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022692 my ($CPath, $Type) = classifyPath($Path);
22693 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022694 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022695 }
22696 }
22697 if($ParamNamesPath)
22698 {
22699 if(not -f $ParamNamesPath) {
22700 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22701 }
22702 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22703 {
22704 if($Line=~s/\A(\w+)\;//)
22705 {
22706 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022707 if($Line=~/;(\d+);/)
22708 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022709 while($Line=~s/(\d+);(\w+)//) {
22710 $AddIntParams{$Interface}{$1}=$2;
22711 }
22712 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022713 else
22714 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022715 my $Num = 0;
22716 foreach my $Name (split(/;/, $Line)) {
22717 $AddIntParams{$Interface}{$Num++}=$Name;
22718 }
22719 }
22720 }
22721 }
22722 }
22723 if($AppPath)
22724 {
22725 if(not -f $AppPath) {
22726 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22727 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022728
22729 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022730 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022731 $SymbolsList_App{$Interface} = 1;
22732 }
22733 }
22734 if($DumpAPI)
22735 { # --dump-abi
22736 # make an API dump
22737 create_ABI_Dump();
22738 exit($COMPILE_ERRORS);
22739 }
22740 # default: compare APIs
22741 # -d1 <path>
22742 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022743 compareInit();
22744 if($JoinReport or $DoubleReport)
22745 {
22746 compareAPIs("Binary");
22747 compareAPIs("Source");
22748 }
22749 elsif($BinaryOnly) {
22750 compareAPIs("Binary");
22751 }
22752 elsif($SourceOnly) {
22753 compareAPIs("Source");
22754 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022755 exitReport();
22756}
22757
22758scenario();