blob: 636608856c047571bb1c97dfb9dbce6e08380cd1 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +03003# ABI Compliance Checker (ABICC) 1.99.14.2
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 Ponomarenkodfd12452015-11-12 15:49:25 +030067my $TOOL_VERSION = "1.99.14.2";
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
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002399 if($NBid ne $Bid
2400 and $NBid ne $Tid)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002401 {
2402 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2403 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2404 }
2405 }
2406 }
2407 }
2408 }
2409 }
2410}
2411
2412sub createType($$)
2413{
2414 my ($Attr, $LibVersion) = @_;
2415 my $NewId = ++$MAX_ID;
2416
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002417 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002418 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002419 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002420
2421 return "$NewId";
2422}
2423
2424sub instType($$$)
2425{ # create template instances
2426 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002427
2428 if(not $TypeInfo{$LibVersion}{$Tid}) {
2429 return undef;
2430 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002431 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2432
2433 foreach my $Key (sort keys(%{$Map}))
2434 {
2435 if(my $Val = $Map->{$Key})
2436 {
2437 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2438
2439 if(defined $Attr->{"NameSpace"}) {
2440 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2441 }
2442 foreach (keys(%{$Attr->{"TParam"}})) {
2443 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2444 }
2445 }
2446 else
2447 { # remove absent
2448 # _Traits, etc.
2449 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002450 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002451 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2452 }
2453 foreach (keys(%{$Attr->{"TParam"}}))
2454 {
2455 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2456 delete($Attr->{"TParam"}{$_});
2457 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002458 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002459 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2460 }
2461 }
2462 }
2463 }
2464
2465 my $Tmpl = 0;
2466
2467 if(defined $Attr->{"TParam"})
2468 {
2469 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2470 {
2471 my $PName = $Attr->{"TParam"}{$_}{"name"};
2472
2473 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2474 {
2475 my %Base = get_BaseType($PTid, $LibVersion);
2476
2477 if($Base{"Type"} eq "TemplateParam"
2478 or defined $Base{"Template"})
2479 {
2480 $Tmpl = 1;
2481 last
2482 }
2483 }
2484 }
2485 }
2486
2487 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2488 return "$Id";
2489 }
2490 else
2491 {
2492 if(not $Tmpl) {
2493 delete($Attr->{"Template"});
2494 }
2495
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002496 my $New = createType($Attr, $LibVersion);
2497
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002498 my %EMap = ();
2499 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2500 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2501 }
2502 foreach (keys(%{$Map})) {
2503 $EMap{$_} = $Map->{$_};
2504 }
2505
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002506 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2507 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002508 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002509 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002510 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002511 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002512 {
2513 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2514
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03002515 if($NBid ne $Bid
2516 and $NBid ne $New)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002517 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002518 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2519 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002520 }
2521 }
2522 }
2523
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002524 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002525 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002526 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2527 {
2528 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2529 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2530 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002531 }
2532 }
2533
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002534 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002535 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002536 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2537 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002538 }
2539 }
2540
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002541 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2542 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002543 }
2544
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002545 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002546 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002547}
2548
2549sub addMissedTypes_Pre()
2550{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002551 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002552 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2553 { # detecting missed typedefs
2554 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2555 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002556 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002557 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002558 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002559 if($TypeType eq "Unknown")
2560 { # template_type_parm
2561 next;
2562 }
2563 my $TypeDeclId = getTypeDeclId($TypeId);
2564 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2565 my $TypedefName = getNameByInfo($MissedTDid);
2566 next if(not $TypedefName);
2567 next if($TypedefName eq "__float80");
2568 next if(isAnon($TypedefName));
2569 if(not $TypeDeclId
2570 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002571 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002572 }
2573 }
2574 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002575 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002576 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002577 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002578 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002579 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002580 next;
2581 }
2582 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002583 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002584 if(not $TypedefName) {
2585 next;
2586 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002587 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002588 my %MissedInfo = ( # typedef info
2589 "Name" => $TypedefName,
2590 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002591 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002592 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002593 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002594 my ($H, $L) = getLocation($MissedTDid);
2595 $MissedInfo{"Header"} = $H;
2596 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002597 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002598 { # other types
2599 next;
2600 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002601 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002602 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002603 next;
2604 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002605 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002606 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002607 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002608 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002609 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002610 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002611 next;
2612 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002613 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002614 next;
2615 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002616 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002617 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002618 next;
2619 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002620 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002621 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002622 next;
2623 }
2624 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002625
2626 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2627
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002628 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002629 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002630 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002631 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002632 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002633
2634 # add missed & remove other
2635 $TypeInfo{$Version} = \%AddTypes;
2636 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002637}
2638
2639sub addMissedTypes_Post()
2640{
2641 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2642 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002643 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2644 {
2645 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2646 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2647 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2648 }
2649 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002650 }
2651}
2652
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002653sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002654{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002655 my $TypeId = $_[0];
2656 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2657 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002658 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002659 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002660 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002661}
2662
2663sub getArraySize($$)
2664{
2665 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002666 if(my $Size = getSize($TypeId))
2667 {
2668 my $Elems = $Size/$BYTE_SIZE;
2669 while($BaseName=~s/\s*\[(\d+)\]//) {
2670 $Elems/=$1;
2671 }
2672 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2673 {
2674 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2675 $Elems/=$BasicSize;
2676 }
2677 }
2678 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002679 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002680 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002681}
2682
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002683sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002684{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002685 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002686 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002687 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2688 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002689 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002690 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2691 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2692 if(not $NodeType)
2693 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002694 return ();
2695 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002696 if($NodeType eq "tree_vec")
2697 {
2698 if($Pos!=$#Positions)
2699 { # select last vector of parameters ( ns<P1>::type<P2> )
2700 next;
2701 }
2702 }
2703 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2704 foreach my $P (@Params)
2705 {
2706 if($P eq "") {
2707 return ();
2708 }
2709 elsif($P ne "\@skip\@") {
2710 @TmplParams = (@TmplParams, $P);
2711 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002712 }
2713 }
2714 return @TmplParams;
2715}
2716
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002717sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002718{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002719 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002720 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002721 if(defined $TypeInfo{$Version}{$TypeId}
2722 and $TypeInfo{$Version}{$TypeId}{"Name"})
2723 { # already created
2724 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002725 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002726 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2727 { # incomplete type
2728 return ();
2729 }
2730 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2731
2732 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002733 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002734
2735 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2736 {
2737 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2738 {
2739 if($Info=~/qual[ ]*:/)
2740 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002741 my $NewId = ++$MAX_ID;
2742
2743 $MissedBase{$Version}{$TypeId} = "$NewId";
2744 $MissedBase_R{$Version}{$NewId} = $TypeId;
2745 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2746 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002747 }
2748 }
2749 $TypeAttr{"Type"} = "Typedef";
2750 }
2751 else {
2752 $TypeAttr{"Type"} = getTypeType($TypeId);
2753 }
2754
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002755 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2756 {
2757 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2758 { # local code
2759 return ();
2760 }
2761 }
2762
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002763 if($TypeAttr{"Type"} eq "Unknown") {
2764 return ();
2765 }
2766 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2767 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002768 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002769 if(my $TName = $TypeAttr{"Name"})
2770 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002771 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002772 $TName_Tid{$Version}{$TName} = $TypeId;
2773 return %TypeAttr;
2774 }
2775 else {
2776 return ();
2777 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002778 }
2779 elsif($TypeAttr{"Type"} eq "Array")
2780 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002781 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2782 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002783 return ();
2784 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002785 if(my $Algn = getAlgn($TypeId)) {
2786 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2787 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002788 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002789 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002790 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002791 if(not $BTAttr{"Name"}) {
2792 return ();
2793 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002794 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002795 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002796 if(my $Size = getSize($TypeId)) {
2797 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2798 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002799 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002800 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2801 }
2802 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002803 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002804 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002805 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002806 else
2807 {
2808 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002809 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002810 $TypeAttr{"Name"} = $1."[]".$2;
2811 }
2812 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002813 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002814 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002815 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002816 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002817 if($BTAttr{"Header"}) {
2818 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002819 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002820 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002821 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2822 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002823 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002824 return ();
2825 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002826 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002827 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002828 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002829 if($TypeAttr{"Name"})
2830 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002831 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002832
2833 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2834 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002835 { # NOTE: register only one int: with built-in decl
2836 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2837 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2838 }
2839 }
2840 return %TypeAttr;
2841 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002842 else {
2843 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002844 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002845 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002846 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2847 {
2848 %TypeAttr = getTrivialTypeAttr($TypeId);
2849 if($TypeAttr{"Name"})
2850 {
2851 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2852 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2853 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2854 }
2855 return %TypeAttr;
2856 }
2857 else {
2858 return ();
2859 }
2860 }
2861 elsif($TypeAttr{"Type"} eq "SizeOf")
2862 {
2863 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2864 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2865 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2866 if($TypeAttr{"Name"})
2867 {
2868 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2869 return %TypeAttr;
2870 }
2871 else {
2872 return ();
2873 }
2874 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002875 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002876 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002877 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2878 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002879 return ();
2880 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002881 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002882 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002883 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002884 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002885 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002886 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002887 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002888 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002889 }
2890 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002891 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002892 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002893 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002894 return ();
2895 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002896 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002897 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002898 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002899 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002900 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002901 }
2902 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002903 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002904 {
2905 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002906 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002907 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002908 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002909 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2910 }
2911 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002912 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002913 }
2914 }
2915 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002916 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002917 }
2918 if($TypeAttr{"Type"} eq "Typedef")
2919 {
2920 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002921
2922 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2923 return ();
2924 }
2925
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002926 if(isAnon($TypeAttr{"Name"}))
2927 { # anon typedef to anon type: ._N
2928 return ();
2929 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002930
2931 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2932 { # artificial typedef of "struct X" to "X"
2933 $TypeAttr{"Artificial"} = 1;
2934 }
2935
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002936 if(my $NS = getNameSpace($TypeDeclId))
2937 {
2938 my $TypeName = $TypeAttr{"Name"};
2939 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2940 { # "some_type" is the typedef to "struct some_type" in C++
2941 if($3) {
2942 $TypeAttr{"Name"} = $3."::".$TypeName;
2943 }
2944 }
2945 else
2946 {
2947 $TypeAttr{"NameSpace"} = $NS;
2948 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002949
2950 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2951 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
2952 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002953 if($BTAttr{"NameSpace"}
2954 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002955 { # types like "std::fpos<__mbstate_t>" are
2956 # not covered by typedefs in the TU dump
2957 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002958 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2959 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002960 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002961 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002962 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002963 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002964 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002965 }
2966 }
2967 }
2968 }
2969 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002970 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002971 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002972 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002973 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
2974 { # typedef int*const TYPEDEF; // first
2975 # int foo(TYPEDEF p); // const is optimized out
2976 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
2977 if($BTAttr{"Name"}=~/</)
2978 {
2979 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
2980 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2981 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002982 }
2983 }
2984 }
2985 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
2986 }
2987 if(not $TypeAttr{"Size"})
2988 {
2989 if($TypeAttr{"Type"} eq "Pointer") {
2990 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
2991 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002992 elsif($BTAttr{"Size"}) {
2993 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002994 }
2995 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002996 if(my $Algn = getAlgn($TypeId)) {
2997 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2998 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002999 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003000 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3001 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003002 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003003 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003004 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003005 { # typedef to "class Class"
3006 # should not be registered in TName_Tid
3007 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3008 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3009 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003010 }
3011 return %TypeAttr;
3012 }
3013}
3014
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003015sub getTreeVec($)
3016{
3017 my %Vector = ();
3018 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3019 {
3020 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3021 { # string length is N-1 because of the null terminator
3022 $Vector{$1} = $2;
3023 }
3024 }
3025 return \%Vector;
3026}
3027
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003028sub get_TemplateParam($$)
3029{
3030 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003031 return () if(not $Type_Id);
3032 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3033 return () if(not $NodeType);
3034 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003035 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003036 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003037 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003038 my $Num = getNodeIntCst($Type_Id);
3039 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003040 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003041 }
3042 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003043 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003044 }
3045 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003046 elsif($NodeType eq "string_cst") {
3047 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003048 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003049 elsif($NodeType eq "tree_vec")
3050 {
3051 my $Vector = getTreeVec($Type_Id);
3052 my @Params = ();
3053 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3054 {
3055 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3056 push(@Params, $P2);
3057 }
3058 }
3059 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003060 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003061 elsif($NodeType eq "parm_decl")
3062 {
3063 (getNameByInfo($Type_Id));
3064 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003065 else
3066 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003067 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003068 my $PName = $ParamAttr{"Name"};
3069 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003070 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003071 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003072 if($PName=~/\>/)
3073 {
3074 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003075 $PName = $Cover;
3076 }
3077 }
3078 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003079 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003080 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3081 # template<typename _Key, typename _Compare = std::less<_Key>
3082 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3083 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3084 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3085 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003086 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003087 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003088 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003089 }
3090}
3091
3092sub cover_stdcxx_typedef($)
3093{
3094 my $TypeName = $_[0];
3095 if(my @Covers = sort {length($a)<=>length($b)}
3096 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3097 { # take the shortest typedef
3098 # FIXME: there may be more than
3099 # one typedefs to the same type
3100 return $Covers[0];
3101 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003102 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003103 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3104 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3105 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003106 if(my $Cover = $Covers[0])
3107 {
3108 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3109 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3110 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003111 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003112 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003113}
3114
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003115sub getNodeIntCst($)
3116{
3117 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003118 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003119 if($EnumMembName_Id{$Version}{$CstId}) {
3120 return $EnumMembName_Id{$Version}{$CstId};
3121 }
3122 elsif((my $Value = getTreeValue($CstId)) ne "")
3123 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003124 if($Value eq "0")
3125 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003126 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003127 return "false";
3128 }
3129 else {
3130 return "0";
3131 }
3132 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003133 elsif($Value eq "1")
3134 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003135 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003136 return "true";
3137 }
3138 else {
3139 return "1";
3140 }
3141 }
3142 else {
3143 return $Value;
3144 }
3145 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003146 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003147}
3148
3149sub getNodeStrCst($)
3150{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003151 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3152 {
3153 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003154 {
3155 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3156 { # string length is N-1 because of the null terminator
3157 return substr($1, 0, $2-1);
3158 }
3159 else
3160 { # identifier_node
3161 return substr($1, 0, $2);
3162 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003163 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003164 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003165 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003166}
3167
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003168sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003169{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003170 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003171 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3172 if($Type eq "FieldPtr") {
3173 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3174 }
3175 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3176 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003177 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003178 if($Type eq "MethodPtr")
3179 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003180 if(my $Size = getSize($TypeId))
3181 {
3182 $Size/=$BYTE_SIZE;
3183 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003184 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003185 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003186 if(my $Algn = getAlgn($TypeId)) {
3187 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3188 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003189 # Return
3190 if($Type eq "FieldPtr")
3191 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003192 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003193 if($ReturnAttr{"Name"}) {
3194 $MemPtrName .= $ReturnAttr{"Name"};
3195 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003196 $TypeAttr{"Return"} = $PtrId;
3197 }
3198 else
3199 {
3200 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3201 {
3202 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003203 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3204 if(not $ReturnAttr{"Name"})
3205 { # templates
3206 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003207 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003208 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003209 $TypeAttr{"Return"} = $ReturnTypeId;
3210 }
3211 }
3212 # Class
3213 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3214 {
3215 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003216 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003217 if($Class{"Name"}) {
3218 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3219 }
3220 else {
3221 $MemPtrName .= " (*)";
3222 }
3223 }
3224 else {
3225 $MemPtrName .= " (*)";
3226 }
3227 # Parameters
3228 if($Type eq "FuncPtr"
3229 or $Type eq "MethodPtr")
3230 {
3231 my @ParamTypeName = ();
3232 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3233 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003234 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003235 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003236 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003237 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003238 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3239 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003240 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003241 my $PTypeId = $1;
3242 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003243 if(not $ParamAttr{"Name"})
3244 { # templates (template_type_parm), etc.
3245 return ();
3246 }
3247 if($ParamAttr{"Name"} eq "void") {
3248 last;
3249 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003250 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003251 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003252 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003253 push(@ParamTypeName, $ParamAttr{"Name"});
3254 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003255 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3256 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003257 }
3258 else {
3259 last;
3260 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003261 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003262 else {
3263 last;
3264 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003265 }
3266 }
3267 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3268 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003269 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003270 return %TypeAttr;
3271}
3272
3273sub getTreeTypeName($)
3274{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003275 my $TypeId = $_[0];
3276 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003277 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003278 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003279 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003280 if(my $Name = getNameByInfo($TypeId))
3281 { # bit_size_type
3282 return $Name;
3283 }
3284 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003285 return "unsigned int";
3286 }
3287 else {
3288 return "int";
3289 }
3290 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003291 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003292 return getNameByInfo($1);
3293 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003294 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003295 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003296}
3297
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003298sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003299{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003300 my $Ptd = pointTo($_[0]);
3301 return 0 if(not $Ptd);
3302 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003303 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003304 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3305 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003306 }
3307 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003308 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3309 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003310 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003311 if($InfoT1 eq "pointer_type"
3312 and $InfoT2 eq "function_type") {
3313 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003314 }
3315 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003316 return 0;
3317}
3318
3319sub isMethodPtr($)
3320{
3321 my $Ptd = pointTo($_[0]);
3322 return 0 if(not $Ptd);
3323 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3324 {
3325 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3326 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3327 and $Info=~/ ptrmem /) {
3328 return 1;
3329 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003330 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003331 return 0;
3332}
3333
3334sub isFieldPtr($)
3335{
3336 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3337 {
3338 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3339 and $Info=~/ ptrmem /) {
3340 return 1;
3341 }
3342 }
3343 return 0;
3344}
3345
3346sub pointTo($)
3347{
3348 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3349 {
3350 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3351 return $1;
3352 }
3353 }
3354 return "";
3355}
3356
3357sub getTypeTypeByTypeId($)
3358{
3359 my $TypeId = $_[0];
3360 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3361 {
3362 my $NType = $NodeType{$TType};
3363 if($NType eq "Intrinsic") {
3364 return $NType;
3365 }
3366 elsif(isFuncPtr($TypeId)) {
3367 return "FuncPtr";
3368 }
3369 elsif(isMethodPtr($TypeId)) {
3370 return "MethodPtr";
3371 }
3372 elsif(isFieldPtr($TypeId)) {
3373 return "FieldPtr";
3374 }
3375 elsif($NType ne "Other") {
3376 return $NType;
3377 }
3378 }
3379 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003380}
3381
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003382my %UnQual = (
3383 "r"=>"restrict",
3384 "v"=>"volatile",
3385 "c"=>"const",
3386 "cv"=>"const volatile"
3387);
3388
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003389sub getQual($)
3390{
3391 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003392 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3393 {
3394 my ($Qual, $To) = ();
3395 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3396 $Qual = $UnQual{$1};
3397 }
3398 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3399 $To = $1;
3400 }
3401 if($Qual and $To) {
3402 return ($Qual, $To);
3403 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003404 }
3405 return ();
3406}
3407
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003408sub getQualType($)
3409{
3410 if($_[0] eq "const volatile") {
3411 return "ConstVolatile";
3412 }
3413 return ucfirst($_[0]);
3414}
3415
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003416sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003417{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003418 my $TypeId = $_[0];
3419 my $TypeDeclId = getTypeDeclId($TypeId);
3420 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003421 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003422 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3423 return "Typedef";
3424 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003425 }
3426 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3427 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003428 if(($Qual or $To) and $TypeDeclId
3429 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003430 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003431 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003432 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003433 elsif(not $MissedBase_R{$Version}{$TypeId}
3434 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003435 return "Typedef";
3436 }
3437 elsif($Qual)
3438 { # qualified types
3439 return getQualType($Qual);
3440 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003441
3442 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3443 { # typedef struct { ... } name
3444 $TypeTypedef{$Version}{$TypeId} = $1;
3445 }
3446
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003447 my $TypeType = getTypeTypeByTypeId($TypeId);
3448 if($TypeType eq "Struct")
3449 {
3450 if($TypeDeclId
3451 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3452 return "Template";
3453 }
3454 }
3455 return $TypeType;
3456}
3457
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003458sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003459{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003460 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003461 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003462 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3463 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3464 return 0;
3465 }
3466 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3467 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003468 if(my $TDid = getTypeDeclId($_[0]))
3469 {
3470 if(getTypeId($TDid) eq $_[0]
3471 and getNameByInfo($TDid))
3472 {
3473 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3474 return $1;
3475 }
3476 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003477 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003478 }
3479 }
3480 return 0;
3481}
3482
3483sub selectBaseType($)
3484{
3485 my $TypeId = $_[0];
3486 if(defined $MissedTypedef{$Version}{$TypeId})
3487 { # add missed typedefs
3488 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3489 return ($TypeId, "");
3490 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003491 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003492 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3493 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003494
3495 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3496 my $MB = $MissedBase{$Version}{$TypeId};
3497
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003498 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003499 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003500 and (getTypeId($1) ne $TypeId)
3501 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003502 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003503 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003504 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003505 elsif($MB)
3506 { # add base
3507 return ($MB, "");
3508 }
3509 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003510 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003511 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003512 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003513 elsif($Qual or $To)
3514 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003515 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003516 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003517 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003518 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003519 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003520 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003521 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003522 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003523 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003524 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003525 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003526 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003527 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003528 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003529 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003530 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003531 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003532 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003533 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003534 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003535
3536 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003537}
3538
3539sub getSymbolInfo_All()
3540{
3541 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3542 { # reverse order
3543 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003544 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003545 }
3546 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003547
3548 if($ADD_TMPL_INSTANCES)
3549 {
3550 # templates
3551 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3552 {
3553 my %Map = ();
3554
3555 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3556 {
3557 if(defined $TemplateMap{$Version}{$ClassId})
3558 {
3559 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3560 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3561 }
3562 }
3563 }
3564
3565 if(defined $TemplateMap{$Version}{$Sid})
3566 {
3567 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3568 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3569 }
3570 }
3571
3572 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3573 {
3574 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3575 {
3576 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3577 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3578 }
3579 }
3580 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3581 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3582 }
3583 }
3584 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003585}
3586
3587sub getVarInfo_All()
3588{
3589 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3590 { # reverse order
3591 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003592 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003593 }
3594 }
3595}
3596
3597sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003598 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003599}
3600
3601sub getVarInfo($)
3602{
3603 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003604 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003605 {
3606 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3607 if($NSInfoType and $NSInfoType eq "function_decl") {
3608 return;
3609 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003610 }
3611 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3612 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3613 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3614 delete($SymbolInfo{$Version}{$InfoId});
3615 return;
3616 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003617 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003618 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003619 delete($SymbolInfo{$Version}{$InfoId});
3620 return;
3621 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003622 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3623 delete($SymbolInfo{$Version}{$InfoId});
3624 return;
3625 }
3626 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003627 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3628 {
3629 if($OSgroup eq "windows")
3630 { # cut the offset
3631 $MnglName=~s/\@\d+\Z//g;
3632 }
3633 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3634 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003635 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003636 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003637 { # validate mangled name
3638 delete($SymbolInfo{$Version}{$InfoId});
3639 return;
3640 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003641 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003642 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003643 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003644 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003645 }
3646 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3647 { # non-public global data
3648 delete($SymbolInfo{$Version}{$InfoId});
3649 return;
3650 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003651 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003652 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003653 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003654 if(not defined $TypeInfo{$Version}{$Rid}
3655 or not $TypeInfo{$Version}{$Rid}{"Name"})
3656 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003657 delete($SymbolInfo{$Version}{$InfoId});
3658 return;
3659 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003660 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3661 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003662 if(defined $Val) {
3663 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3664 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003665 }
3666 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003667 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3668 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003669 if(not defined $TypeInfo{$Version}{$ClassId}
3670 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3671 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003672 delete($SymbolInfo{$Version}{$InfoId});
3673 return;
3674 }
3675 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003676 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3677 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003678 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003679 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003680 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003681 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003682 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003683 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003684 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003685 if(not $CheckHeadersOnly)
3686 {
3687 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3688 {
3689 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3690 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3691 {
3692 if(link_symbol($ShortName, $Version, "-Deps"))
3693 { # "const" global data is mangled as _ZL... in the TU dump
3694 # but not mangled when compiling a C shared library
3695 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3696 }
3697 }
3698 }
3699 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003700 if($COMMON_LANGUAGE{$Version} eq "C++")
3701 {
3702 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3703 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003704 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003705 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3706 }
3707 }
3708 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3709 { # try to mangle symbol (link with libraries)
3710 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3711 }
3712 if($OStarget eq "windows")
3713 {
3714 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3715 { # link MS C++ symbols from library with GCC symbols from headers
3716 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3717 }
3718 }
3719 }
3720 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3721 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3722 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003723 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3724 {
3725 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3726 { # non-target symbols
3727 delete($SymbolInfo{$Version}{$InfoId});
3728 return;
3729 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003730 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003731 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3732 {
3733 if(defined $MissedTypedef{$Version}{$Rid})
3734 {
3735 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3736 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3737 }
3738 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003739 }
3740 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003741 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003742 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3743 }
3744 if($ShortName=~/\A(_Z|\?)/) {
3745 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3746 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003747
3748 if($ExtraDump) {
3749 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3750 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003751}
3752
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003753sub isConstType($$)
3754{
3755 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003756 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003757 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003758 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003759 }
3760 return ($Base{"Type"} eq "Const");
3761}
3762
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003763sub getTrivialName($$)
3764{
3765 my ($TypeInfoId, $TypeId) = @_;
3766 my %TypeAttr = ();
3767 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3768 if(not $TypeAttr{"Name"}) {
3769 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3770 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003771 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003772 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003773 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003774 if(isAnon($TypeAttr{"Name"}))
3775 {
3776 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003777 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003778 { # searching for a first not anon scope
3779 if($NSId eq $NameSpaceId) {
3780 last;
3781 }
3782 else
3783 {
3784 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3785 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003786 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003787 last;
3788 }
3789 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003790 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003791 }
3792 }
3793 else
3794 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003795 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003796 {
3797 if($NameSpaceId ne $TypeId) {
3798 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3799 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003800 }
3801 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003802 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003803 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3804 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003805 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003806 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003807 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003808 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003809 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003810 if($TypeAttr{"NameSpace"}) {
3811 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3812 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003813 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003814 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3815 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003816 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003817 if(my @TParams = getTParams($TypeId, "Type")) {
3818 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3819 }
3820 else {
3821 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3822 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003823 }
3824 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3825}
3826
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003827sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003828{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003829 my $TypeId = $_[0];
3830 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003831
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003832 my %TypeAttr = ();
3833
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003834 if($TemplateDecl{$Version}{$TypeId})
3835 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003836 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003837 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003838
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003839 setTypeAccess($TypeId, \%TypeAttr);
3840 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3841 if(isBuiltIn($TypeAttr{"Header"}))
3842 {
3843 delete($TypeAttr{"Header"});
3844 delete($TypeAttr{"Line"});
3845 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003846
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003847 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003848 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3849 if(not $TypeAttr{"Name"}) {
3850 return ();
3851 }
3852 if(not $TypeAttr{"NameSpace"}) {
3853 delete($TypeAttr{"NameSpace"});
3854 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003855
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04003856 if($TypeAttr{"Type"} eq "Intrinsic")
3857 {
3858 if(defined $TypeAttr{"Header"})
3859 {
3860 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
3861 { # support for SUSE 11.2
3862 # integer_type has srcp dump{1-2}.i
3863 delete($TypeAttr{"Header"});
3864 }
3865 }
3866 }
3867
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003868 my $Tmpl = undef;
3869
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003870 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003871 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003872 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3873
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003874 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003875 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003876 foreach my $Pos (0 .. $#TParams)
3877 {
3878 my $Val = $TParams[$Pos];
3879 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3880
3881 if(not defined $TypeAttr{"Template"})
3882 {
3883 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3884
3885 if($Base{"Type"} eq "TemplateParam"
3886 or defined $Base{"Template"}) {
3887 $TypeAttr{"Template"} = 1;
3888 }
3889 }
3890
3891 if($Tmpl)
3892 {
3893 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
3894 {
3895 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
3896
3897 if($Val eq $Arg) {
3898 $TypeAttr{"Template"} = 1;
3899 }
3900 }
3901 }
3902 }
3903
3904 if($Tmpl)
3905 {
3906 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
3907 {
3908 if($Pos>$#TParams)
3909 {
3910 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
3911 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
3912 }
3913 }
3914 }
3915 }
3916
3917 if($ADD_TMPL_INSTANCES)
3918 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003919 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003920 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003921 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003922 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003923 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003924 {
3925 if(my $Flds = getTreeAttr_Flds($MainInst)) {
3926 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
3927 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003928 }
3929 if(not getTreeAttr_Binf($TypeId))
3930 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003931 if(my $Binf = getTreeAttr_Binf($MainInst)) {
3932 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
3933 }
3934 }
3935 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003936 }
3937 }
3938 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003939
3940 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3941
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003942 if(my $Size = getSize($TypeId))
3943 {
3944 $Size = $Size/$BYTE_SIZE;
3945 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003946 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003947 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003948 {
3949 if($ExtraDump)
3950 {
3951 if(not defined $TypeAttr{"Memb"}
3952 and not $Tmpl)
3953 { # declaration only
3954 $TypeAttr{"Forward"} = 1;
3955 }
3956 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003957 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003958
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003959 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003960 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003961 {
3962 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003963 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003964 }
3965 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003966 or $TypeAttr{"Type"} eq "Class")
3967 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003968 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003969 if($Skip) {
3970 return ();
3971 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003972 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003973 if(my $Algn = getAlgn($TypeId)) {
3974 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3975 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003976 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003977
3978 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
3979 {
3980 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003981 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003982 {
3983 if(not isAnon($TypeAttr{"Name"})) {
3984 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
3985 }
3986 }
3987 }
3988
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003989 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003990 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
3991 {
3992 my @Entries = split(/\n/, $VTable);
3993 foreach (1 .. $#Entries)
3994 {
3995 my $Entry = $Entries[$_];
3996 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003997 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003998 }
3999 }
4000 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004001
4002 if($TypeAttr{"Type"} eq "Enum")
4003 {
4004 if(not $TypeAttr{"NameSpace"})
4005 {
4006 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4007 {
4008 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004009 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004010 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004011 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004012 "Header"=>$TypeAttr{"Header"}
4013 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004014 if(isAnon($TypeAttr{"Name"}))
4015 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004016 if($ExtraDump
4017 or is_target_header($TypeAttr{"Header"}, $Version))
4018 {
4019 %{$Constants{$Version}{$MName}} = (
4020 "Value" => $MVal,
4021 "Header" => $TypeAttr{"Header"}
4022 );
4023 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004024 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004025 }
4026 }
4027 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004028 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004029 {
4030 if(defined $TypedefToAnon{$TypeId}) {
4031 $TypeAttr{"AnonTypedef"} = 1;
4032 }
4033 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004034
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004035 return %TypeAttr;
4036}
4037
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004038sub simplifyVTable($)
4039{
4040 my $Content = $_[0];
4041 if($Content=~s/ \[with (.+)]//)
4042 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4043 if(my @Elems = separate_Params($1, 0, 0))
4044 {
4045 foreach my $Elem (@Elems)
4046 {
4047 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4048 {
4049 my ($Arg, $Val) = ($1, $2);
4050
4051 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4052 $Content=~s/,\s*$Arg\b//g;
4053 }
4054 else {
4055 $Content=~s/\b$Arg\b/$Val/g;
4056 }
4057 }
4058 }
4059 }
4060 }
4061
4062 return $Content;
4063}
4064
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004065sub detect_lang($)
4066{
4067 my $TypeId = $_[0];
4068 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004069 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004070 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004071 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4072 }
4073 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004074 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004075 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004076 while($Fncs)
4077 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004078 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004079 return 1;
4080 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004081 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004082 }
4083 }
4084 return 0;
4085}
4086
4087sub setSpec($$)
4088{
4089 my ($TypeId, $TypeAttr) = @_;
4090 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4091 if($Info=~/\s+spec\s+/) {
4092 $TypeAttr->{"Spec"} = 1;
4093 }
4094}
4095
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004096sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004097{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004098 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004099 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004100 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004101 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004102 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004103 my $Pos = 0;
4104 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4105 {
4106 my ($Access, $BInfoId) = ($1, $2);
4107 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004108
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +03004109 if($ClassId eq $TypeId)
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004110 { # class A<N>:public A<N-1>
4111 next;
4112 }
4113
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004114 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4115 if(not $CType or $CType eq "template_type_parm"
4116 or $CType eq "typename_type")
4117 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004118 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004119 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004120 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004121 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004122 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4123 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004124 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004125 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4126 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004127 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004128 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004129 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004130 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4131 }
4132 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004133 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004134 }
4135 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004136 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004137}
4138
4139sub getBinfClassId($)
4140{
4141 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
4142 $Info=~/type[ ]*:[ ]*@(\d+) /;
4143 return $1;
4144}
4145
4146sub unmangledFormat($$)
4147{
4148 my ($Name, $LibVersion) = @_;
4149 $Name = uncover_typedefs($Name, $LibVersion);
4150 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4151 $Name=~s/\(\w+\)(\d)/$1/;
4152 return $Name;
4153}
4154
4155sub modelUnmangled($$)
4156{
4157 my ($InfoId, $Compiler) = @_;
4158 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4159 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4160 }
4161 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4162 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4163 $PureSignature = "~".$PureSignature;
4164 }
4165 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4166 {
4167 my (@Params, @ParamTypes) = ();
4168 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4169 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4170 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4171 }
4172 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4173 { # checking parameters
4174 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004175 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004176 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004177 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004178
4179 if($PName eq "this"
4180 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4181 {
4182 next;
4183 }
4184
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004185 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004186 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004187 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004188 }
4189 @ParamTypes = (@ParamTypes, $PTName);
4190 }
4191 if(@ParamTypes) {
4192 $PureSignature .= "(".join(", ", @ParamTypes).")";
4193 }
4194 else
4195 {
4196 if($Compiler eq "MSVC")
4197 {
4198 $PureSignature .= "(void)";
4199 }
4200 else
4201 { # GCC
4202 $PureSignature .= "()";
4203 }
4204 }
4205 $PureSignature = delete_keywords($PureSignature);
4206 }
4207 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4208 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004209 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004210 $PureSignature = $ClassName."::".$PureSignature;
4211 }
4212 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4213 $PureSignature = $NS."::".$PureSignature;
4214 }
4215 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4216 $PureSignature .= " const";
4217 }
4218 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4219 $PureSignature .= " volatile";
4220 }
4221 my $ShowReturn = 0;
4222 if($Compiler eq "MSVC"
4223 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4224 {
4225 $ShowReturn=1;
4226 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004227 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4228 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004229 {
4230 $ShowReturn=1;
4231 }
4232 if($ShowReturn)
4233 { # mangled names for template function specializations include return value
4234 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4235 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004236 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004237 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4238 $PureSignature = $ReturnName." ".$PureSignature;
4239 }
4240 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004241 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004242}
4243
4244sub mangle_symbol($$$)
4245{ # mangling for simple methods
4246 # see gcc-4.6.0/gcc/cp/mangle.c
4247 my ($InfoId, $LibVersion, $Compiler) = @_;
4248 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4249 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4250 }
4251 my $Mangled = "";
4252 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004253 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004254 }
4255 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004256 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004257 }
4258 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4259}
4260
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004261sub mangle_symbol_MSVC($$)
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04004262{ # TODO
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004263 my ($InfoId, $LibVersion) = @_;
4264 return "";
4265}
4266
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004267sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004268{ # see gcc-4.6.0/gcc/cp/mangle.c
4269 my ($InfoId, $LibVersion) = @_;
4270 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004271 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004272 my %Repl = ();# SN_ replacements
4273 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4274 {
4275 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4276 if($MangledClass!~/\AN/) {
4277 $MangledClass = "N".$MangledClass;
4278 }
4279 else {
4280 $MangledClass=~s/E\Z//;
4281 }
4282 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4283 $MangledClass=~s/\AN/NV/;
4284 }
4285 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4286 $MangledClass=~s/\AN/NK/;
4287 }
4288 $Mangled .= $MangledClass;
4289 }
4290 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4291 { # mangled by name due to the absence of structured info
4292 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4293 if($MangledNS!~/\AN/) {
4294 $MangledNS = "N".$MangledNS;
4295 }
4296 else {
4297 $MangledNS=~s/E\Z//;
4298 }
4299 $Mangled .= $MangledNS;
4300 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004301 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004302 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004303 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004304 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004305 foreach (@TPos) {
4306 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4307 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004308 }
4309 elsif($TmplParams)
4310 { # remangling mode
4311 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004312 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004313 }
4314 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4315 $Mangled .= "C1";
4316 }
4317 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4318 $Mangled .= "D0";
4319 }
4320 elsif($ShortName)
4321 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004322 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4323 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004324 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004325 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004326 { # "const" global data is mangled as _ZL...
4327 $Mangled .= "L";
4328 }
4329 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004330 if($ShortName=~/\Aoperator(\W.*)\Z/)
4331 {
4332 my $Op = $1;
4333 $Op=~s/\A[ ]+//g;
4334 if(my $OpMngl = $OperatorMangling{$Op}) {
4335 $Mangled .= $OpMngl;
4336 }
4337 else { # conversion operator
4338 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4339 }
4340 }
4341 else {
4342 $Mangled .= length($ShortName).$ShortName;
4343 }
4344 if(@TParams)
4345 { # templates
4346 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004347 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004348 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4349 }
4350 $Mangled .= "E";
4351 }
4352 if(not $ClassId and @TParams) {
4353 add_substitution($ShortName, \%Repl, 0);
4354 }
4355 }
4356 if($ClassId or $NameSpace) {
4357 $Mangled .= "E";
4358 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004359 if(@TParams)
4360 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004361 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004362 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4363 }
4364 }
4365 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4366 {
4367 my @Params = ();
4368 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4369 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4370 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4371 }
4372 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4373 { # checking parameters
4374 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4375 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4376 }
4377 if(not @Params) {
4378 $Mangled .= "v";
4379 }
4380 }
4381 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4382 $Mangled = write_stdcxx_substitution($Mangled);
4383 if($Mangled eq "_Z") {
4384 return "";
4385 }
4386 return $Mangled;
4387}
4388
4389sub correct_incharge($$$)
4390{
4391 my ($InfoId, $LibVersion, $Mangled) = @_;
4392 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4393 {
4394 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004395 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004396 }
4397 }
4398 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4399 {
4400 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004401 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004402 }
4403 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004404 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004405 }
4406 }
4407 return $Mangled;
4408}
4409
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004410sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004411{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004412 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004413 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004414 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004415 return $Name;
4416 }
4417 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004418 while(my $CPos = find_center($TParams, "<"))
4419 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004420 $TParams = substr($TParams, $CPos);
4421 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004422 if($TParams=~s/\A<(.+)>\Z/$1/) {
4423 $Name=~s/<\Q$TParams\E>\Z//;
4424 }
4425 else
4426 { # error
4427 $TParams = "";
4428 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004429 return ($Name, $TParams);
4430}
4431
4432sub get_sub_ns($)
4433{
4434 my $Name = $_[0];
4435 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004436 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004437 {
4438 push(@NS, substr($Name, 0, $CPos));
4439 $Name = substr($Name, $CPos);
4440 $Name=~s/\A:://;
4441 }
4442 return (join("::", @NS), $Name);
4443}
4444
4445sub mangle_ns($$$)
4446{
4447 my ($Name, $LibVersion, $Repl) = @_;
4448 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4449 {
4450 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4451 $Mangled=~s/\AN(.+)E\Z/$1/;
4452 return $Mangled;
4453
4454 }
4455 else
4456 {
4457 my ($MangledNS, $SubNS) = ("", "");
4458 ($SubNS, $Name) = get_sub_ns($Name);
4459 if($SubNS) {
4460 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4461 }
4462 $MangledNS .= length($Name).$Name;
4463 add_substitution($MangledNS, $Repl, 0);
4464 return $MangledNS;
4465 }
4466}
4467
4468sub mangle_param($$$)
4469{
4470 my ($PTid, $LibVersion, $Repl) = @_;
4471 my ($MPrefix, $Mangled) = ("", "");
4472 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004473 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004474 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004475 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004476 if(not $BaseType_Name) {
4477 return "";
4478 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004479 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004480 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004481 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4482 while($Suffix=~/(&|\*|const)\Z/)
4483 {
4484 if($Suffix=~s/[ ]*&\Z//) {
4485 $MPrefix .= "R";
4486 }
4487 if($Suffix=~s/[ ]*\*\Z//) {
4488 $MPrefix .= "P";
4489 }
4490 if($Suffix=~s/[ ]*const\Z//)
4491 {
4492 if($MPrefix=~/R|P/
4493 or $Suffix=~/&|\*/) {
4494 $MPrefix .= "K";
4495 }
4496 }
4497 if($Suffix=~s/[ ]*volatile\Z//) {
4498 $MPrefix .= "V";
4499 }
4500 #if($Suffix=~s/[ ]*restrict\Z//) {
4501 #$MPrefix .= "r";
4502 #}
4503 }
4504 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4505 $Mangled .= $Token;
4506 }
4507 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4508 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004509 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004510 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004511 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004512 foreach (@TPos) {
4513 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4514 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004515 }
4516 elsif($TmplParams)
4517 { # remangling mode
4518 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004519 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004520 }
4521 my $MangledNS = "";
4522 my ($SubNS, $SName) = get_sub_ns($ShortName);
4523 if($SubNS) {
4524 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4525 }
4526 $MangledNS .= length($SName).$SName;
4527 if(@TParams) {
4528 add_substitution($MangledNS, $Repl, 0);
4529 }
4530 $Mangled .= "N".$MangledNS;
4531 if(@TParams)
4532 { # templates
4533 $Mangled .= "I";
4534 foreach my $TParam (@TParams) {
4535 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4536 }
4537 $Mangled .= "E";
4538 }
4539 $Mangled .= "E";
4540 }
4541 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4542 {
4543 if($BaseType{"Type"} eq "MethodPtr") {
4544 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4545 }
4546 else {
4547 $Mangled .= "PF";
4548 }
4549 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4550 my @Params = keys(%{$BaseType{"Param"}});
4551 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4552 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4553 }
4554 if(not @Params) {
4555 $Mangled .= "v";
4556 }
4557 $Mangled .= "E";
4558 }
4559 elsif($BaseType{"Type"} eq "FieldPtr")
4560 {
4561 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4562 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4563 }
4564 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4565 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4566 {
4567 if($Mangled eq $Optimized)
4568 {
4569 if($ShortName!~/::/)
4570 { # remove "N ... E"
4571 if($MPrefix) {
4572 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4573 }
4574 else {
4575 $Mangled=~s/\AN(.+)E\Z/$1/g;
4576 }
4577 }
4578 }
4579 else {
4580 $Mangled = $Optimized;
4581 }
4582 }
4583 add_substitution($Mangled, $Repl, 1);
4584 return $Mangled;
4585}
4586
4587sub mangle_template_param($$$)
4588{ # types + literals
4589 my ($TParam, $LibVersion, $Repl) = @_;
4590 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4591 return mangle_param($TPTid, $LibVersion, $Repl);
4592 }
4593 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4594 { # class_name<1u>::method(...)
4595 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4596 }
4597 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4598 { # class_name<(signed char)1>::method(...)
4599 return "L".$IntrinsicMangling{$1}.$2."E";
4600 }
4601 elsif($TParam eq "true")
4602 { # class_name<true>::method(...)
4603 return "Lb1E";
4604 }
4605 elsif($TParam eq "false")
4606 { # class_name<true>::method(...)
4607 return "Lb0E";
4608 }
4609 else { # internal error
4610 return length($TParam).$TParam;
4611 }
4612}
4613
4614sub add_substitution($$$)
4615{
4616 my ($Value, $Repl, $Rec) = @_;
4617 if($Rec)
4618 { # subtypes
4619 my @Subs = ($Value);
4620 while($Value=~s/\A(R|P|K)//) {
4621 push(@Subs, $Value);
4622 }
4623 foreach (reverse(@Subs)) {
4624 add_substitution($_, $Repl, 0);
4625 }
4626 return;
4627 }
4628 return if($Value=~/\AS(\d*)_\Z/);
4629 $Value=~s/\AN(.+)E\Z/$1/g;
4630 return if(defined $Repl->{$Value});
4631 return if(length($Value)<=1);
4632 return if($StdcxxMangling{$Value});
4633 # check for duplicates
4634 my $Base = $Value;
4635 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4636 {
4637 my $Num = $Repl->{$Type};
4638 my $Replace = macro_mangle($Num);
4639 $Base=~s/\Q$Replace\E/$Type/;
4640 }
4641 if(my $OldNum = $Repl->{$Base})
4642 {
4643 $Repl->{$Value} = $OldNum;
4644 return;
4645 }
4646 my @Repls = sort {$b<=>$a} values(%{$Repl});
4647 if(@Repls) {
4648 $Repl->{$Value} = $Repls[0]+1;
4649 }
4650 else {
4651 $Repl->{$Value} = -1;
4652 }
4653 # register duplicates
4654 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004655 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004656 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4657 {
4658 next if($Base eq $Type);
4659 my $Num = $Repl->{$Type};
4660 my $Replace = macro_mangle($Num);
4661 $Base=~s/\Q$Type\E/$Replace/;
4662 $Repl->{$Base} = $Repl->{$Value};
4663 }
4664}
4665
4666sub macro_mangle($)
4667{
4668 my $Num = $_[0];
4669 if($Num==-1) {
4670 return "S_";
4671 }
4672 else
4673 {
4674 my $Code = "";
4675 if($Num<10)
4676 { # S0_, S1_, S2_, ...
4677 $Code = $Num;
4678 }
4679 elsif($Num>=10 and $Num<=35)
4680 { # SA_, SB_, SC_, ...
4681 $Code = chr(55+$Num);
4682 }
4683 else
4684 { # S10_, S11_, S12_
4685 $Code = $Num-26; # 26 is length of english alphabet
4686 }
4687 return "S".$Code."_";
4688 }
4689}
4690
4691sub write_stdcxx_substitution($)
4692{
4693 my $Mangled = $_[0];
4694 if($StdcxxMangling{$Mangled}) {
4695 return $StdcxxMangling{$Mangled};
4696 }
4697 else
4698 {
4699 my @Repls = keys(%StdcxxMangling);
4700 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4701 foreach my $MangledType (@Repls)
4702 {
4703 my $Replace = $StdcxxMangling{$MangledType};
4704 #if($Mangled!~/$Replace/) {
4705 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4706 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4707 #}
4708 }
4709 }
4710 return $Mangled;
4711}
4712
4713sub write_substitution($$)
4714{
4715 my ($Mangled, $Repl) = @_;
4716 if(defined $Repl->{$Mangled}
4717 and my $MnglNum = $Repl->{$Mangled}) {
4718 $Mangled = macro_mangle($MnglNum);
4719 }
4720 else
4721 {
4722 my @Repls = keys(%{$Repl});
4723 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4724 # FIXME: how to apply replacements? by num or by pos
4725 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4726 foreach my $MangledType (@Repls)
4727 {
4728 my $Replace = macro_mangle($Repl->{$MangledType});
4729 if($Mangled!~/$Replace/) {
4730 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4731 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4732 }
4733 }
4734 }
4735 return $Mangled;
4736}
4737
4738sub delete_keywords($)
4739{
4740 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004741 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004742 return $TypeName;
4743}
4744
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004745sub uncover_typedefs($$)
4746{
4747 my ($TypeName, $LibVersion) = @_;
4748 return "" if(not $TypeName);
4749 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4750 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4751 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004752 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004753 while($TypeName_New ne $TypeName_Pre)
4754 {
4755 $TypeName_Pre = $TypeName_New;
4756 my $TypeName_Copy = $TypeName_New;
4757 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004758 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004759 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004760 if(not $Intrinsic_Keywords{$1}) {
4761 $Words{$1} = 1;
4762 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004763 }
4764 foreach my $Word (keys(%Words))
4765 {
4766 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4767 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004768 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004769 if($BaseType_Name=~/\([\*]+\)/)
4770 { # FuncPtr
4771 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4772 {
4773 my $Type_Suffix = $1;
4774 $TypeName_New = $BaseType_Name;
4775 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004776 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004777 }
4778 }
4779 }
4780 else
4781 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004782 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004783 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004784 }
4785 }
4786 }
4787 }
4788 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4789}
4790
4791sub isInternal($)
4792{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004793 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4794 {
4795 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4796 {
4797 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4798 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4799 return 1;
4800 }
4801 }
4802 }
4803 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004804}
4805
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004806sub getDataVal($$)
4807{
4808 my ($InfoId, $TypeId) = @_;
4809 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4810 {
4811 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4812 {
4813 if(defined $LibInfo{$Version}{"info_type"}{$1}
4814 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004815 {
4816 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004817 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004818 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4819 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004820 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004821 if(my $Addr = getTreeAttr_Op($1)) {
4822 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004823 }
4824 }
4825 }
4826 }
4827 else {
4828 return getInitVal($1, $TypeId);
4829 }
4830 }
4831 }
4832 return undef;
4833}
4834
4835sub getInitVal($$)
4836{
4837 my ($InfoId, $TypeId) = @_;
4838 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4839 {
4840 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4841 {
4842 if($InfoType eq "integer_cst")
4843 {
4844 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004845 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004846 { # characters
4847 $Val = chr($Val);
4848 }
4849 return $Val;
4850 }
4851 elsif($InfoType eq "string_cst") {
4852 return getNodeStrCst($InfoId);
4853 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004854 elsif($InfoType eq "var_decl")
4855 {
4856 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4857 return $Name;
4858 }
4859 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004860 }
4861 }
4862 return undef;
4863}
4864
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004865sub set_Class_And_Namespace($)
4866{
4867 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004868 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004869 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004870 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004871 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004872 my $NSInfoId = $1;
4873 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4874 {
4875 if($InfoType eq "namespace_decl") {
4876 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4877 }
4878 elsif($InfoType eq "record_type") {
4879 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4880 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004881 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004882 }
4883 }
4884 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4885 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004886 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004887 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004888 { # skip
4889 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004890 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004891 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004892
4893 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004894}
4895
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004896sub debugMangling($)
4897{
4898 my $LibVersion = $_[0];
4899 my %Mangled = ();
4900 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4901 {
4902 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4903 {
4904 if($Mngl=~/\A(_Z|\?)/) {
4905 $Mangled{$Mngl}=$InfoId;
4906 }
4907 }
4908 }
4909 translateSymbols(keys(%Mangled), $LibVersion);
4910 foreach my $Mngl (keys(%Mangled))
4911 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004912 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4913 my $U2 = $tr_name{$Mngl};
4914 if($U1 ne $U2) {
4915 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004916 }
4917 }
4918}
4919
4920sub linkSymbol($)
4921{ # link symbols from shared libraries
4922 # with the symbols from header files
4923 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004924 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004925 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004926 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4927 or $EMERGENCY_MODE_48)
4928 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4929 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
4930 # GCC 4.8 doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004931 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004932 {
4933 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4934 return correct_incharge($InfoId, $Version, $Mangled);
4935 }
4936 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004937 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004938 or not $BinaryOnly
4939 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004940 { # 1. --headers-only mode
4941 # 2. not mangled src-only symbols
4942 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4943 return $Mangled;
4944 }
4945 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004946 }
4947 return "";
4948}
4949
4950sub setLanguage($$)
4951{
4952 my ($LibVersion, $Lang) = @_;
4953 if(not $UserLang) {
4954 $COMMON_LANGUAGE{$LibVersion} = $Lang;
4955 }
4956}
4957
4958sub getSymbolInfo($)
4959{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004960 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004961 if(isInternal($InfoId)) {
4962 return;
4963 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004964 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
4965 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004966 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
4967 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004968 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004969 return;
4970 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004971 setFuncAccess($InfoId);
4972 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004973 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
4974 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004975 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004976 return;
4977 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004978
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004979 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004980 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004981 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004982 if(not defined $TypeInfo{$Version}{$Return}
4983 or not $TypeInfo{$Version}{$Return}{"Name"})
4984 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004985 delete($SymbolInfo{$Version}{$InfoId});
4986 return;
4987 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004988 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004989 }
4990 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
4991 {
4992 if(defined $MissedTypedef{$Version}{$Rid})
4993 {
4994 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
4995 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
4996 }
4997 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004998 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004999 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5000 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005001 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005002 my $Orig = getFuncOrig($InfoId);
5003 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005004 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5005 {
5006 delete($SymbolInfo{$Version}{$InfoId});
5007 return;
5008 }
5009
5010 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005011 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005012 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005013 return;
5014 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005015
5016 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005017 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005018 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5019
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005020 my @TParams = getTParams($Orig, "Func");
5021 if(not @TParams)
5022 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005023 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005024 return;
5025 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005026 foreach my $Pos (0 .. $#TParams)
5027 {
5028 my $Val = $TParams[$Pos];
5029 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5030
5031 if($Tmpl)
5032 {
5033 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5034 {
5035 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5036 }
5037 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005038 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005039
5040 if($Tmpl)
5041 {
5042 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5043 {
5044 if($Pos>$#TParams)
5045 {
5046 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5047 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5048 }
5049 }
5050 }
5051
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005052 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5053 { # operator<< <T>, operator>> <T>
5054 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5055 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005056 if(@TParams) {
5057 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5058 }
5059 else {
5060 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5061 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005062 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005063 }
5064 else
5065 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005066 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005067 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005068 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5069 {
5070 if($OSgroup eq "windows")
5071 { # cut the offset
5072 $MnglName=~s/\@\d+\Z//g;
5073 }
5074 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5075
5076 # NOTE: mangling of some symbols may change depending on GCC version
5077 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5078 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5079 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005080
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005081 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005082 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005083 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005084 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005085 return;
5086 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005087 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005088 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005089 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005090 if($Skip)
5091 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005092 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005093 return;
5094 }
5095 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005096 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5097 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5098 }
5099
5100 if(set_Class_And_Namespace($InfoId))
5101 {
5102 delete($SymbolInfo{$Version}{$InfoId});
5103 return;
5104 }
5105
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005106 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5107 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005108 if(not defined $TypeInfo{$Version}{$ClassId}
5109 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5110 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005111 delete($SymbolInfo{$Version}{$InfoId});
5112 return;
5113 }
5114 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005115 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5116 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005117 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005118 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005119 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005120 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005121 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005122 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005123 }
5124 if($COMMON_LANGUAGE{$Version} eq "C++")
5125 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005126 # C++ or --headers-only mode
5127 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005128 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005129 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5130 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005131 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005132 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005133 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005134 if(my $Mangled = linkSymbol($InfoId)) {
5135 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005136 }
5137 }
5138 if($OStarget eq "windows")
5139 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005140 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005141 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005142 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005143 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005144 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005145 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005146 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005147 }
5148 }
5149 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005150 else
5151 { # not mangled in C
5152 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5153 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005154 if(not $CheckHeadersOnly
5155 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5156 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5157 {
5158 my $Incorrect = 0;
5159
5160 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5161 {
5162 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5163 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5164 { # mangled in the TU dump, but not mangled in the library
5165 $Incorrect = 1;
5166 }
5167 }
5168 else
5169 {
5170 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5171 { # all C++ functions are not mangled in the TU dump
5172 $Incorrect = 1;
5173 }
5174 }
5175 if($Incorrect)
5176 {
5177 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5178 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5179 }
5180 }
5181 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005182 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005183 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005184 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005185 return;
5186 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005187 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005188 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005189 { # identify virtual and pure virtual functions
5190 # NOTE: constructors cannot be virtual
5191 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5192 # in the TU dump, so taking it from the original symbol
5193 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5194 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5195 { # NOTE: D2 destructors are not present in a v-table
5196 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5197 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005198 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005199 if(isInline($InfoId)) {
5200 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005201 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005202 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005203 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5204 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005205 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5206 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005207 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005208 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005209 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005210 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005211 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005212 }
5213 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005214 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5215 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005216 if(not $ExtraDump)
5217 {
5218 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5219 { # non-target symbols
5220 delete($SymbolInfo{$Version}{$InfoId});
5221 return;
5222 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005223 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005224 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005225 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5226 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5227 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5228 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005229 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005230 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5231 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005232 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005233 return;
5234 }
5235 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005236 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005237 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005238 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005239 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005240 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005241 return;
5242 }
5243 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005244 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005245 }
5246 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005247 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5248 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5249 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005250 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005251 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5252 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005253 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005254 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005255 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005256 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005257 }
5258 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005259 if(getFuncLink($InfoId) eq "Static") {
5260 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005261 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005262 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5263 {
5264 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5265 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005266 if($Unmangled=~/\.\_\d/)
5267 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005268 delete($SymbolInfo{$Version}{$InfoId});
5269 return;
5270 }
5271 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005272 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005273
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005274 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5275 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005276 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005277 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5278 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005279 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005280
5281 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5282 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5283 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005284
5285 if($ExtraDump) {
5286 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5287 }
5288}
5289
5290sub guessHeader($)
5291{
5292 my $InfoId = $_[0];
5293 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5294 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5295 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5296 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5297 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5298 {
5299 if(get_filename($HPath) eq $Header)
5300 {
5301 my $HDir = get_filename(get_dirname($HPath));
5302 if($HDir ne "include"
5303 and $HDir=~/\A[a-z]+\Z/i) {
5304 return join_P($HDir, $Header);
5305 }
5306 }
5307 }
5308 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005309}
5310
5311sub isInline($)
5312{ # "body: undefined" in the tree
5313 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005314 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5315 {
5316 if($Info=~/ undefined /i) {
5317 return 0;
5318 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005319 }
5320 return 1;
5321}
5322
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005323sub hasThrow($)
5324{
5325 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5326 {
5327 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5328 return getTreeAttr_Unql($1, "unql");
5329 }
5330 }
5331 return 1;
5332}
5333
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005334sub getTypeId($)
5335{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005336 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5337 {
5338 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5339 return $1;
5340 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005341 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005342 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005343}
5344
5345sub setTypeMemb($$)
5346{
5347 my ($TypeId, $TypeAttr) = @_;
5348 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005349 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005350 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005351 if($TypeType eq "Enum")
5352 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005353 my $MInfoId = getTreeAttr_Csts($TypeId);
5354 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005355 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005356 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5357 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005358 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005359 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5360 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005361 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005362 }
5363 }
5364 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5365 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005366 my $MInfoId = getTreeAttr_Flds($TypeId);
5367 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005368 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005369 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5370 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005371 if(not $IType or $IType ne "field_decl")
5372 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005373
5374 if($IType eq "var_decl")
5375 { # static field
5376 $StaticFields = 1;
5377 }
5378
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005379 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005380 next;
5381 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005382 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005383 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005384 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005385 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005386 }
5387 if(not $StructMembName)
5388 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005389 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005390 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005391 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005392 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5393 if(isAnon($UnnamedTName))
5394 { # rename unnamed fields to unnamed0, unnamed1, ...
5395 $StructMembName = "unnamed".($UnnamedPos++);
5396 }
5397 }
5398 }
5399 if(not $StructMembName)
5400 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005401 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005402 next;
5403 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005404 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005405 if(defined $MissedTypedef{$Version}{$MembTypeId})
5406 {
5407 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5408 $MembTypeId = $AddedTid;
5409 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005410 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005411
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005412 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5413 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005414 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005415 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005416 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5417 }
5418 if($MInfo=~/spec:\s*mutable /)
5419 { # mutable fields
5420 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005421 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005422 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005423 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5424 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005425 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005426 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005427 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005428 }
5429 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005430 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005431 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5432 { # template
5433 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5434 }
5435 else {
5436 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5437 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005438 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005439
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005440 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005441 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005442 }
5443 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005444
5445 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005446}
5447
5448sub setFuncParams($)
5449{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005450 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005451 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005452
5453 my $FType = getFuncType($InfoId);
5454
5455 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005456 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005457 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5458 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005459 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005460 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005461 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5462 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005463 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005464 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5465 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005466 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005467 else
5468 { # skip
5469 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005470 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005471 # skip "this"-parameter
5472 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005473 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005474 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005475 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005476 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005477 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5478 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5479 if(not $ParamName)
5480 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005481 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005482 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005483 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5484 {
5485 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5486 $ParamTypeId = $AddedTid;
5487 }
5488 }
5489 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005490 if(not $PType or $PType eq "Unknown") {
5491 return 1;
5492 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005493 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005494 if(not $PTName) {
5495 return 1;
5496 }
5497 if($PTName eq "void") {
5498 last;
5499 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005500 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005501 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005502 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005503 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005504 $ParamInfoId = getNextElem($ParamInfoId);
5505 next;
5506 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005507 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005508
5509 if(my %Base = get_BaseType($ParamTypeId, $Version))
5510 {
5511 if(defined $Base{"Template"}) {
5512 return 1;
5513 }
5514 }
5515
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005516 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005517 if(my $Algn = getAlgn($ParamInfoId)) {
5518 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5519 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005520 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5521 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005522 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005523 }
5524 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005525 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005526 if($ParamName ne "this" or $FType ne "Method") {
5527 $PPos += 1;
5528 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005529 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005530 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005531 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005532 }
5533 return 0;
5534}
5535
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005536sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005537{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005538 my ($InfoId, $Vtt_Pos) = @_;
5539 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005540 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005541 my $FType = getFuncType($InfoId);
5542
5543 if($FType eq "Method")
5544 {
5545 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005546 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005547 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005548 if(not $ParamListElemId)
5549 { # foo(...)
5550 return 1;
5551 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005552 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005553 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005554 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005555 { # actual params: may differ from formal args
5556 # formal int*const
5557 # actual: int*
5558 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005559 {
5560 $Vtt_Pos=-1;
5561 $ParamListElemId = getNextElem($ParamListElemId);
5562 next;
5563 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005564 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5565 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005566 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005567 $HaveVoid = 1;
5568 last;
5569 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005570 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005571 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005572 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5573 {
5574 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5575 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5576 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005577 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005578 }
5579 }
5580 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5581 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005582 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005583 { # params
5584 if($OldId ne $ParamTypeId)
5585 {
5586 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5587 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5588
5589 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5590 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5591 }
5592 }
5593 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005594 }
5595 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005596 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005597 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005598 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5599 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005600 if($PurpType eq "nop_expr")
5601 { # func ( const char* arg = (const char*)(void*)0 )
5602 $PurpId = getTreeAttr_Op($PurpId);
5603 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005604 my $Val = getInitVal($PurpId, $ParamTypeId);
5605 if(defined $Val) {
5606 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5607 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005608 }
5609 }
5610 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005611 if($Pos!=0 or $FType ne "Method") {
5612 $PPos += 1;
5613 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005614 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005615 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005616 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005617}
5618
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005619sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005620{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005621 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5622 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005623 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5624 return $1;
5625 }
5626 }
5627 return "";
5628}
5629
5630sub getTreeAttr_Chain($)
5631{
5632 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5633 {
5634 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5635 return $1;
5636 }
5637 }
5638 return "";
5639}
5640
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005641sub getTreeAttr_Unql($)
5642{
5643 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5644 {
5645 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5646 return $1;
5647 }
5648 }
5649 return "";
5650}
5651
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005652sub getTreeAttr_Scpe($)
5653{
5654 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5655 {
5656 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5657 return $1;
5658 }
5659 }
5660 return "";
5661}
5662
5663sub getTreeAttr_Type($)
5664{
5665 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5666 {
5667 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5668 return $1;
5669 }
5670 }
5671 return "";
5672}
5673
5674sub getTreeAttr_Name($)
5675{
5676 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5677 {
5678 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5679 return $1;
5680 }
5681 }
5682 return "";
5683}
5684
5685sub getTreeAttr_Mngl($)
5686{
5687 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5688 {
5689 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5690 return $1;
5691 }
5692 }
5693 return "";
5694}
5695
5696sub getTreeAttr_Prms($)
5697{
5698 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5699 {
5700 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5701 return $1;
5702 }
5703 }
5704 return "";
5705}
5706
5707sub getTreeAttr_Fncs($)
5708{
5709 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5710 {
5711 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5712 return $1;
5713 }
5714 }
5715 return "";
5716}
5717
5718sub getTreeAttr_Csts($)
5719{
5720 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5721 {
5722 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5723 return $1;
5724 }
5725 }
5726 return "";
5727}
5728
5729sub getTreeAttr_Purp($)
5730{
5731 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5732 {
5733 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5734 return $1;
5735 }
5736 }
5737 return "";
5738}
5739
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005740sub getTreeAttr_Op($)
5741{
5742 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5743 {
5744 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5745 return $1;
5746 }
5747 }
5748 return "";
5749}
5750
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005751sub getTreeAttr_Valu($)
5752{
5753 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5754 {
5755 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5756 return $1;
5757 }
5758 }
5759 return "";
5760}
5761
5762sub getTreeAttr_Flds($)
5763{
5764 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5765 {
5766 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5767 return $1;
5768 }
5769 }
5770 return "";
5771}
5772
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005773sub getTreeAttr_Binf($)
5774{
5775 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5776 {
5777 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5778 return $1;
5779 }
5780 }
5781 return "";
5782}
5783
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005784sub getTreeAttr_Args($)
5785{
5786 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5787 {
5788 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005789 return $1;
5790 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005791 }
5792 return "";
5793}
5794
5795sub getTreeValue($)
5796{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005797 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5798 {
5799 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5800 return $1;
5801 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005802 }
5803 return "";
5804}
5805
5806sub getTreeAccess($)
5807{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005808 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005809 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005810 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5811 {
5812 my $Access = $1;
5813 if($Access eq "prot") {
5814 return "protected";
5815 }
5816 elsif($Access eq "priv") {
5817 return "private";
5818 }
5819 }
5820 elsif($Info=~/ protected /)
5821 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005822 return "protected";
5823 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005824 elsif($Info=~/ private /)
5825 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005826 return "private";
5827 }
5828 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005829 return "public";
5830}
5831
5832sub setFuncAccess($)
5833{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005834 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005835 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005836 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005837 }
5838 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005839 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005840 }
5841}
5842
5843sub setTypeAccess($$)
5844{
5845 my ($TypeId, $TypeAttr) = @_;
5846 my $Access = getTreeAccess($TypeId);
5847 if($Access eq "protected") {
5848 $TypeAttr->{"Protected"} = 1;
5849 }
5850 elsif($Access eq "private") {
5851 $TypeAttr->{"Private"} = 1;
5852 }
5853}
5854
5855sub setFuncKind($)
5856{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005857 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5858 {
5859 if($Info=~/pseudo tmpl/) {
5860 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5861 }
5862 elsif($Info=~/ constructor /) {
5863 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5864 }
5865 elsif($Info=~/ destructor /) {
5866 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5867 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005868 }
5869}
5870
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005871sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005872{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005873 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5874 {
5875 if($Info=~/spec[ ]*:[ ]*pure /) {
5876 return "PureVirt";
5877 }
5878 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5879 return "Virt";
5880 }
5881 elsif($Info=~/ pure\s+virtual /)
5882 { # support for old GCC versions
5883 return "PureVirt";
5884 }
5885 elsif($Info=~/ virtual /)
5886 { # support for old GCC versions
5887 return "Virt";
5888 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005889 }
5890 return "";
5891}
5892
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005893sub getFuncLink($)
5894{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005895 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5896 {
5897 if($Info=~/link[ ]*:[ ]*static /) {
5898 return "Static";
5899 }
5900 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005901 return $1;
5902 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005903 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005904 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005905}
5906
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005907sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005908{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005909 my ($Symbol, $LibVersion) = @_;
5910 return "" if(not $Symbol or not $LibVersion);
5911 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5912 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005913 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005914 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5915 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5916 }
5917 }
5918 if($NS)
5919 {
5920 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5921 return $NS;
5922 }
5923 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005924 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005925 while($NS=~s/::[^:]+\Z//)
5926 {
5927 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5928 return $NS;
5929 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005930 }
5931 }
5932 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005933
5934 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005935}
5936
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005937sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005938{
5939 my ($TypeName, $LibVersion) = @_;
5940 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005941 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005942 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005943 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5944 return $NS;
5945 }
5946 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005947 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005948 while($NS=~s/::[^:]+\Z//)
5949 {
5950 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5951 return $NS;
5952 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005953 }
5954 }
5955 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005956 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005957}
5958
5959sub getNameSpace($)
5960{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005961 my $InfoId = $_[0];
5962 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005963 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005964 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005965 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005966 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005967 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005968 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
5969 {
5970 my $NameSpace = getTreeStr($1);
5971 if($NameSpace eq "::")
5972 { # global namespace
5973 return "";
5974 }
5975 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
5976 $NameSpace = $BaseNameSpace."::".$NameSpace;
5977 }
5978 $NestedNameSpaces{$Version}{$NameSpace} = 1;
5979 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005980 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005981 else {
5982 return "";
5983 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005984 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005985 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005986 { # inside data type
5987 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
5988 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005989 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005990 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005991 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005992 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005993}
5994
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005995sub getEnumMembVal($)
5996{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005997 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005998 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005999 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6000 {
6001 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6002 {
6003 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6004 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6005 return getTreeValue($1);
6006 }
6007 else
6008 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6009 return getTreeValue($1);
6010 }
6011 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006012 }
6013 }
6014 return "";
6015}
6016
6017sub getSize($)
6018{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006019 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6020 {
6021 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6022 return getTreeValue($1);
6023 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006024 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006025 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006026}
6027
6028sub getAlgn($)
6029{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006030 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6031 {
6032 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6033 return $1;
6034 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006035 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006036 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006037}
6038
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006039sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006040{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006041 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6042 {
6043 if($Info=~/ bitfield /) {
6044 return getSize($_[0]);
6045 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006046 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006047 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006048}
6049
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006050sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006051{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006052 if(my $Chan = getTreeAttr_Chan($_[0])) {
6053 return $Chan;
6054 }
6055 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6056 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006057 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006058 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006059}
6060
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006061sub registerHeader($$)
6062{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006063 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006064 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006065 return "";
6066 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006067 if(is_abs($Header) and not -f $Header)
6068 { # incorrect absolute path
6069 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006070 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006071 if(skipHeader($Header, $LibVersion))
6072 { # skip
6073 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006074 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006075 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6076 {
6077 detect_header_includes($Header_Path, $LibVersion);
6078
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006079 if(defined $Tolerance and $Tolerance=~/3/)
6080 { # 3 - skip headers that include non-Linux headers
6081 if($OSgroup ne "windows")
6082 {
6083 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6084 {
6085 if(specificHeader($Inc, "windows")) {
6086 return "";
6087 }
6088 }
6089 }
6090 }
6091
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006092 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6093 { # redirect
6094 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6095 or skipHeader($RHeader_Path, $LibVersion))
6096 { # skip
6097 return "";
6098 }
6099 $Header_Path = $RHeader_Path;
6100 }
6101 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6102 { # skip
6103 return "";
6104 }
6105
6106 if(my $HName = get_filename($Header_Path))
6107 { # register
6108 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6109 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6110 }
6111
6112 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6113 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006114 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006115 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006116 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006117 }
6118
6119 if($CheckHeadersOnly
6120 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6121 { # /usr/include/c++/4.6.1/...
6122 $STDCXX_TESTING = 1;
6123 }
6124
6125 return $Header_Path;
6126 }
6127 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006128}
6129
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006130sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006131{
6132 my ($Dir, $WithDeps, $LibVersion) = @_;
6133 $Dir=~s/[\/\\]+\Z//g;
6134 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006135 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006136
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006137 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006138 if($WithDeps)
6139 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006140 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6141 return;
6142 }
6143 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6144 $Mode = "DepsOnly";
6145 }
6146 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006147 else
6148 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006149 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6150 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6151 return;
6152 }
6153 }
6154 $Header_Dependency{$LibVersion}{$Dir} = 1;
6155 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6156 if($Mode eq "DepsOnly")
6157 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006158 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006159 $Header_Dependency{$LibVersion}{$Path} = 1;
6160 }
6161 return;
6162 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006163 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006164 {
6165 if($WithDeps)
6166 {
6167 my $SubDir = $Path;
6168 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6169 { # register all sub directories
6170 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6171 }
6172 }
6173 next if(is_not_header($Path));
6174 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006175 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006176 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006177 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6178 }
6179 }
6180 if(get_filename($Dir) eq "include")
6181 { # search for "lib/include/" directory
6182 my $LibDir = $Dir;
6183 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006184 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006185 }
6186 }
6187}
6188
6189sub parse_redirect($$$)
6190{
6191 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006192 my @Errors = ();
6193 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6194 push(@Errors, $1);
6195 }
6196 my $Redirect = "";
6197 foreach (@Errors)
6198 {
6199 s/\s{2,}/ /g;
6200 if(/(only|must\ include
6201 |update\ to\ include
6202 |replaced\ with
6203 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006204 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006205 {
6206 $Redirect = $2;
6207 last;
6208 }
6209 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6210 {
6211 $Redirect = $2;
6212 last;
6213 }
6214 elsif(/this\ header\ should\ not\ be\ used
6215 |programs\ should\ not\ directly\ include
6216 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6217 |is\ not\ supported\ API\ for\ general\ use
6218 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006219 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006220 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6221 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6222 }
6223 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006224 if($Redirect)
6225 {
6226 $Redirect=~s/\A<//g;
6227 $Redirect=~s/>\Z//g;
6228 }
6229 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006230}
6231
6232sub parse_includes($$)
6233{
6234 my ($Content, $Path) = @_;
6235 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006236 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006237 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006238 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006239 my $Method = substr($Header, 0, 1, "");
6240 substr($Header, length($Header)-1, 1, "");
6241 $Header = path_format($Header, $OSgroup);
6242 if($Method eq "\"" or is_abs($Header))
6243 {
6244 if(-e join_P(get_dirname($Path), $Header))
6245 { # relative path exists
6246 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006247 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006248 else
6249 { # include "..." that doesn't exist is equal to include <...>
6250 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006251 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006252 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006253 else {
6254 $Includes{$Header} = 1;
6255 }
6256 }
6257 if($ExtraInfo)
6258 {
6259 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6260 { # FT_FREETYPE_H
6261 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006262 }
6263 }
6264 return \%Includes;
6265}
6266
6267sub ignore_path($)
6268{
6269 my $Path = $_[0];
6270 if($Path=~/\~\Z/)
6271 {# skipping system backup files
6272 return 1;
6273 }
6274 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6275 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6276 return 1;
6277 }
6278 return 0;
6279}
6280
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006281sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006282{
6283 my ($ArrRef, $W) = @_;
6284 return if(length($W)<2);
6285 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6286}
6287
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006288sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006289{
6290 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006291
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006292 $H1=~s/\.[a-z]+\Z//ig;
6293 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006294
6295 my $Hname1 = get_filename($H1);
6296 my $Hname2 = get_filename($H2);
6297 my $HDir1 = get_dirname($H1);
6298 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006299 my $Dirname1 = get_filename($HDir1);
6300 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006301
6302 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6303 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6304
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006305 if($_[0] eq $_[1]
6306 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006307 return 0;
6308 }
6309 elsif($H1=~/\A\Q$H2\E/) {
6310 return 1;
6311 }
6312 elsif($H2=~/\A\Q$H1\E/) {
6313 return -1;
6314 }
6315 elsif($HDir1=~/\Q$Hname1\E/i
6316 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006317 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006318 return -1;
6319 }
6320 elsif($HDir2=~/\Q$Hname2\E/i
6321 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006322 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006323 return 1;
6324 }
6325 elsif($Hname1=~/\Q$Dirname1\E/i
6326 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006327 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006328 return -1;
6329 }
6330 elsif($Hname2=~/\Q$Dirname2\E/i
6331 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006332 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006333 return 1;
6334 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006335 elsif($Hname1=~/(config|lib|util)/i
6336 and $Hname2!~/(config|lib|util)/i)
6337 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006338 return -1;
6339 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006340 elsif($Hname2=~/(config|lib|util)/i
6341 and $Hname1!~/(config|lib|util)/i)
6342 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006343 return 1;
6344 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006345 else
6346 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006347 my $R1 = checkRelevance($H1);
6348 my $R2 = checkRelevance($H2);
6349 if($R1 and not $R2)
6350 { # libebook/e-book.h
6351 return -1;
6352 }
6353 elsif($R2 and not $R1)
6354 { # libebook/e-book.h
6355 return 1;
6356 }
6357 else
6358 {
6359 return (lc($H1) cmp lc($H2));
6360 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006361 }
6362}
6363
6364sub searchForHeaders($)
6365{
6366 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006367
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006368 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006369 registerGccHeaders();
6370
6371 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6372 { # c++ standard include paths
6373 registerCppHeaders();
6374 }
6375
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006376 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006377 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6378 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006379 {
6380 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006381 if($SystemRoot)
6382 {
6383 if(is_abs($Path)) {
6384 $Path = $SystemRoot.$Path;
6385 }
6386 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006387 if(not -e $Path) {
6388 exitStatus("Access_Error", "can't access \'$Path\'");
6389 }
6390 elsif(-f $Path) {
6391 exitStatus("Access_Error", "\'$Path\' - not a directory");
6392 }
6393 elsif(-d $Path)
6394 {
6395 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006396 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006397 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6398 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006399 }
6400 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006401 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006402 }
6403 }
6404 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006405 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006406 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6407 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006408
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006409 # registering directories
6410 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6411 {
6412 next if(not -e $Path);
6413 $Path = get_abs_path($Path);
6414 $Path = path_format($Path, $OSgroup);
6415 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006416 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006417 }
6418 elsif(-f $Path)
6419 {
6420 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006421 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006422 and not $LocalIncludes{$Dir})
6423 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006424 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006425 # if(my $OutDir = get_dirname($Dir))
6426 # { # registering the outer directory
6427 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6428 # and not $LocalIncludes{$OutDir}) {
6429 # registerDir($OutDir, 0, $LibVersion);
6430 # }
6431 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006432 }
6433 }
6434 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006435
6436 # clean memory
6437 %RegisteredDirs = ();
6438
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006439 # registering headers
6440 my $Position = 0;
6441 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6442 {
6443 if(is_abs($Dest) and not -e $Dest) {
6444 exitStatus("Access_Error", "can't access \'$Dest\'");
6445 }
6446 $Dest = path_format($Dest, $OSgroup);
6447 if(is_header($Dest, 1, $LibVersion))
6448 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006449 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006450 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6451 }
6452 }
6453 elsif(-d $Dest)
6454 {
6455 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006456 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006457 {
6458 next if(ignore_path($Path));
6459 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006460 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006461 push(@Registered, $HPath);
6462 }
6463 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006464 @Registered = sort {sortHeaders($a, $b)} @Registered;
6465 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006466 foreach my $Path (@Registered) {
6467 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6468 }
6469 }
6470 else {
6471 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6472 }
6473 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006474
6475 if(defined $Tolerance and $Tolerance=~/4/)
6476 { # 4 - skip headers included by others
6477 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6478 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006479 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006480 delete($Registered_Headers{$LibVersion}{$Path});
6481 }
6482 }
6483 }
6484
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006485 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6486 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006487 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006488 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006489 if(is_abs($Header) and not -f $Header) {
6490 exitStatus("Access_Error", "can't access file \'$Header\'");
6491 }
6492 $Header = path_format($Header, $OSgroup);
6493 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6494 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006495 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006496 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006497 }
6498 else {
6499 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6500 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006501 }
6502 }
6503 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6504 { # set relative paths (for duplicates)
6505 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6506 { # search for duplicates
6507 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6508 my $Prefix = get_dirname($FirstPath);
6509 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6510 { # detect a shortest distinguishing prefix
6511 my $NewPrefix = $1;
6512 my %Identity = ();
6513 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6514 {
6515 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6516 $Identity{$Path} = $1;
6517 }
6518 }
6519 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03006520 { # all names are different with current prefix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006521 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6522 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6523 }
6524 last;
6525 }
6526 $Prefix = $NewPrefix; # increase prefix
6527 }
6528 }
6529 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006530
6531 # clean memory
6532 %HeaderName_Paths = ();
6533
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006534 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6535 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006536 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006537 my ($Pos, $PairPos) = (-1, -1);
6538 my ($Path, $PairPath) = ();
6539 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6540 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6541 foreach my $Header_Path (@Paths)
6542 {
6543 if(get_filename($Header_Path) eq $PairName)
6544 {
6545 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6546 $PairPath = $Header_Path;
6547 }
6548 if(get_filename($Header_Path) eq $HeaderName)
6549 {
6550 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6551 $Path = $Header_Path;
6552 }
6553 }
6554 if($PairPos!=-1 and $Pos!=-1
6555 and int($PairPos)<int($Pos))
6556 {
6557 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6558 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6559 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6560 }
6561 }
6562 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6563 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6564 }
6565}
6566
6567sub detect_real_includes($$)
6568{
6569 my ($AbsPath, $LibVersion) = @_;
6570 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6571 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6572 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6573 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6574 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006575 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6576
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006577 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6578 return () if(not $Path);
6579 open(PREPROC, $Path);
6580 while(<PREPROC>)
6581 {
6582 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6583 {
6584 my $Include = path_format($1, $OSgroup);
6585 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6586 next;
6587 }
6588 if($Include eq $AbsPath) {
6589 next;
6590 }
6591 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6592 }
6593 }
6594 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006595 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6596}
6597
6598sub detect_header_includes($$)
6599{
6600 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006601 return if(not $LibVersion or not $Path);
6602 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6603 return;
6604 }
6605 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6606
6607 if(not -e $Path) {
6608 return;
6609 }
6610
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006611 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006612 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6613 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006614 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006615 {
6616 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006617 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006618 }
6619 if($RedirectPath ne $Path) {
6620 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6621 }
6622 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006623 else
6624 { # can't find
6625 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6626 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006627 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006628 if(my $Inc = parse_includes($Content, $Path))
6629 {
6630 foreach my $Include (keys(%{$Inc}))
6631 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006632 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006633
6634 if(defined $Tolerance and $Tolerance=~/4/)
6635 {
6636 if(my $HPath = identifyHeader($Include, $LibVersion))
6637 {
6638 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6639 }
6640 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006641 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006642 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006643}
6644
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006645sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006646{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006647 my $Path = $_[0];
6648 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006649 if($OStarget eq "symbian")
6650 {
6651 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6652 { # epoc32/include/libc/{stdio, ...}.h
6653 return 1;
6654 }
6655 }
6656 else
6657 {
6658 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6659 { # /usr/include/{stdio, ...}.h
6660 return 1;
6661 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006662 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006663 return 0;
6664}
6665
6666sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006667{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006668 my $Dir = $_[0];
6669 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006670 if($OStarget eq "symbian")
6671 {
6672 if(get_filename($OutDir) eq "libc"
6673 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6674 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6675 return 1;
6676 }
6677 }
6678 else
6679 { # linux
6680 if($OutDir eq "/usr/include"
6681 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6682 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6683 return 1;
6684 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006685 }
6686 return 0;
6687}
6688
6689sub detect_recursive_includes($$)
6690{
6691 my ($AbsPath, $LibVersion) = @_;
6692 return () if(not $AbsPath);
6693 if(isCyclical(\@RecurInclude, $AbsPath)) {
6694 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6695 }
6696 my ($AbsDir, $Name) = separate_path($AbsPath);
6697 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006698 { # system GLIBC internals
6699 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006700 }
6701 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6702 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6703 }
6704 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006705
6706 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6707 { # skip /usr/include/c++/*/ headers
6708 return () if(not $ExtraInfo);
6709 }
6710
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006711 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006712 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006713 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006714 { # check "real" (non-"model") include paths
6715 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6716 pop(@RecurInclude);
6717 return @Paths;
6718 }
6719 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6720 detect_header_includes($AbsPath, $LibVersion);
6721 }
6722 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6723 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006724 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006725 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006726 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006727 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006728 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006729 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006730 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006731 }
6732 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006733 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006734 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006735 { # search for the nearest header
6736 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006737 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006738 if(-f $Candidate) {
6739 $HPath = $Candidate;
6740 }
6741 }
6742 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006743 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006744 }
6745 next if(not $HPath);
6746 if($HPath eq $AbsPath) {
6747 next;
6748 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006749
6750 if($Debug)
6751 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006752# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6753# {
6754# print STDERR "$AbsPath -> $HPath\n";
6755# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006756 }
6757
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006758 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6759 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006760 { # only include <...>, skip include "..." prefixes
6761 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6762 }
6763 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6764 {
6765 if($IncPath eq $AbsPath) {
6766 next;
6767 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006768 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6769 if($RIncType==-1)
6770 { # include "..."
6771 $RIncType = $IncType;
6772 }
6773 elsif($RIncType==2)
6774 {
6775 if($IncType!=-1) {
6776 $RIncType = $IncType;
6777 }
6778 }
6779 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006780 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6781 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6782 }
6783 }
6784 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6785 {
6786 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6787 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6788 { # distinguish math.h from glibc and math.h from the tested library
6789 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6790 last;
6791 }
6792 }
6793 }
6794 pop(@RecurInclude);
6795 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6796}
6797
6798sub find_in_framework($$$)
6799{
6800 my ($Header, $Framework, $LibVersion) = @_;
6801 return "" if(not $Header or not $Framework or not $LibVersion);
6802 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6803 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6804 }
6805 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6806 {
6807 if(get_filename($Dependency) eq $Framework
6808 and -f get_dirname($Dependency)."/".$Header) {
6809 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6810 }
6811 }
6812 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6813}
6814
6815sub find_in_defaults($)
6816{
6817 my $Header = $_[0];
6818 return "" if(not $Header);
6819 if(defined $Cache{"find_in_defaults"}{$Header}) {
6820 return $Cache{"find_in_defaults"}{$Header};
6821 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006822 foreach my $Dir (@DefaultIncPaths,
6823 @DefaultGccPaths,
6824 @DefaultCppPaths,
6825 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006826 {
6827 next if(not $Dir);
6828 if(-f $Dir."/".$Header) {
6829 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6830 }
6831 }
6832 return ($Cache{"find_in_defaults"}{$Header}="");
6833}
6834
6835sub cmp_paths($$)
6836{
6837 my ($Path1, $Path2) = @_;
6838 my @Parts1 = split(/[\/\\]/, $Path1);
6839 my @Parts2 = split(/[\/\\]/, $Path2);
6840 foreach my $Num (0 .. $#Parts1)
6841 {
6842 my $Part1 = $Parts1[$Num];
6843 my $Part2 = $Parts2[$Num];
6844 if($GlibcDir{$Part1}
6845 and not $GlibcDir{$Part2}) {
6846 return 1;
6847 }
6848 elsif($GlibcDir{$Part2}
6849 and not $GlibcDir{$Part1}) {
6850 return -1;
6851 }
6852 elsif($Part1=~/glib/
6853 and $Part2!~/glib/) {
6854 return 1;
6855 }
6856 elsif($Part1!~/glib/
6857 and $Part2=~/glib/) {
6858 return -1;
6859 }
6860 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6861 return $CmpRes;
6862 }
6863 }
6864 return 0;
6865}
6866
6867sub checkRelevance($)
6868{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006869 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006870 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006871
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006872 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006873 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006874 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006875
6876 my $Name = lc(get_filename($Path));
6877 my $Dir = lc(get_dirname($Path));
6878
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006879 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006880
6881 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006882 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006883 my $Len = length($Token);
6884 next if($Len<=1);
6885 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6886 { # include/evolution-data-server-1.4/libebook/e-book.h
6887 return 1;
6888 }
6889 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006890 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006891 return 1;
6892 }
6893 }
6894 return 0;
6895}
6896
6897sub checkFamily(@)
6898{
6899 my @Paths = @_;
6900 return 1 if($#Paths<=0);
6901 my %Prefix = ();
6902 foreach my $Path (@Paths)
6903 {
6904 if($SystemRoot) {
6905 $Path = cut_path_prefix($Path, $SystemRoot);
6906 }
6907 if(my $Dir = get_dirname($Path))
6908 {
6909 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6910 $Prefix{$Dir} += 1;
6911 $Prefix{get_dirname($Dir)} += 1;
6912 }
6913 }
6914 foreach (sort keys(%Prefix))
6915 {
6916 if(get_depth($_)>=3
6917 and $Prefix{$_}==$#Paths+1) {
6918 return 1;
6919 }
6920 }
6921 return 0;
6922}
6923
6924sub isAcceptable($$$)
6925{
6926 my ($Header, $Candidate, $LibVersion) = @_;
6927 my $HName = get_filename($Header);
6928 if(get_dirname($Header))
6929 { # with prefix
6930 return 1;
6931 }
6932 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6933 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6934 return 1;
6935 }
6936 if(checkRelevance($Candidate))
6937 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6938 return 1;
6939 }
6940 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6941 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6942 # /usr/include/qt4/Qt/qsslconfiguration.h
6943 return 1;
6944 }
6945 if($OStarget eq "symbian")
6946 {
6947 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6948 return 1;
6949 }
6950 }
6951 return 0;
6952}
6953
6954sub isRelevant($$$)
6955{ # disallow to search for "abstract" headers in too deep directories
6956 my ($Header, $Candidate, $LibVersion) = @_;
6957 my $HName = get_filename($Header);
6958 if($OStarget eq "symbian")
6959 {
6960 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
6961 return 0;
6962 }
6963 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006964 if($OStarget ne "bsd")
6965 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006966 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
6967 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
6968 return 0;
6969 }
6970 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006971 if($OStarget ne "windows")
6972 {
6973 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
6974 { # skip /usr/include/wine/msvcrt
6975 return 0;
6976 }
6977 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006978 if(not get_dirname($Header)
6979 and $Candidate=~/[\/\\]wx[\/\\]/)
6980 { # do NOT search in system /wx/ directory
6981 # for headers without a prefix: sstream.h
6982 return 0;
6983 }
6984 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
6985 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
6986 { # skip ../c++/3.3.3/ if using ../c++/4.5/
6987 return 0;
6988 }
6989 if($Candidate=~/[\/\\]asm-/
6990 and (my $Arch = getArch($LibVersion)) ne "unknown")
6991 { # arch-specific header files
6992 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
6993 {# skip ../asm-arm/ if using x86 architecture
6994 return 0;
6995 }
6996 }
6997 my @Candidates = getSystemHeaders($HName, $LibVersion);
6998 if($#Candidates==1)
6999 { # unique header
7000 return 1;
7001 }
7002 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7003 if($#SCandidates==1)
7004 { # unique name
7005 return 1;
7006 }
7007 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7008 if(get_depth($Candidate)-$SystemDepth>=5)
7009 { # abstract headers in too deep directories
7010 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7011 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7012 return 0;
7013 }
7014 }
7015 if($Header eq "parser.h"
7016 and $Candidate!~/\/libxml2\//)
7017 { # select parser.h from xml2 library
7018 return 0;
7019 }
7020 if(not get_dirname($Header)
7021 and keys(%{$SystemHeaders{$HName}})>=3)
7022 { # many headers with the same name
7023 # like thread.h included without a prefix
7024 if(not checkFamily(@Candidates)) {
7025 return 0;
7026 }
7027 }
7028 return 1;
7029}
7030
7031sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007032{ # cache function
7033 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7034 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7035 }
7036 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7037}
7038
7039sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007040{
7041 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007042 if(-f $Header) {
7043 return $Header;
7044 }
7045 if(is_abs($Header) and not -f $Header)
7046 { # incorrect absolute path
7047 return "";
7048 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007049 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007050 { # too abstract configuration headers
7051 return "";
7052 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007053 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007054 if($OSgroup ne "windows")
7055 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007056 if(defined $WinHeaders{lc($HName)}
7057 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007058 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007059 return "";
7060 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007061 }
7062 if($OSgroup ne "macos")
7063 {
7064 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007065 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007066 return "";
7067 }
7068 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007069
7070 if(defined $ObsoleteHeaders{$HName})
7071 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007072 return "";
7073 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007074 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7075 {
7076 if(defined $AlienHeaders{$HName}
7077 or defined $AlienHeaders{$Header})
7078 { # alien headers from other systems
7079 return "";
7080 }
7081 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007082
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007083 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007084 { # search in default paths
7085 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007086 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007087 }
7088 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007089 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007090 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007091 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007092 }
7093 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7094 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7095 {
7096 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007097 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007098 }
7099 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007100 # error
7101 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007102}
7103
7104sub getSystemHeaders($$)
7105{
7106 my ($Header, $LibVersion) = @_;
7107 my @Candidates = ();
7108 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7109 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007110 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007111 next;
7112 }
7113 push(@Candidates, $Candidate);
7114 }
7115 return @Candidates;
7116}
7117
7118sub cut_path_prefix($$)
7119{
7120 my ($Path, $Prefix) = @_;
7121 return $Path if(not $Prefix);
7122 $Prefix=~s/[\/\\]+\Z//;
7123 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7124 return $Path;
7125}
7126
7127sub is_default_include_dir($)
7128{
7129 my $Dir = $_[0];
7130 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007131 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007132}
7133
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007134sub identifyHeader($$)
7135{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007136 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007137 if(not $Header) {
7138 return "";
7139 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007140 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007141 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7142 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007143 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007144 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007145}
7146
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007147sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007148{ # search for header by absolute path, relative path or name
7149 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007150 if(-f $Header)
7151 { # it's relative or absolute path
7152 return get_abs_path($Header);
7153 }
7154 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7155 and my $HeaderDir = find_in_defaults($Header))
7156 { # search for libc headers in the /usr/include
7157 # for non-libc target library before searching
7158 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007159 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007160 }
7161 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7162 { # search in the target library paths
7163 return $Path;
7164 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007165 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007166 { # search in the internal GCC include paths
7167 return $DefaultGccHeader{$Header};
7168 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007169 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007170 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007171 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007172 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007173 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007174 { # search in the default G++ include paths
7175 return $DefaultCppHeader{$Header};
7176 }
7177 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7178 { # search everywhere in the system
7179 return $AnyPath;
7180 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007181 elsif($OSgroup eq "macos")
7182 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7183 if(my $Dir = get_dirname($Header))
7184 {
7185 my $RelPath = "Headers\/".get_filename($Header);
7186 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007187 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007188 }
7189 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007190 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007191 # cannot find anything
7192 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007193}
7194
7195sub getLocation($)
7196{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007197 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7198 {
7199 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007200 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007201 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007202 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007203 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007204}
7205
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007206sub getNameByInfo($)
7207{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007208 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007209 {
7210 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7211 {
7212 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7213 {
7214 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7215 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007216 my $Str = $1;
7217 if($CppMode{$Version}
7218 and $Str=~/\Ac99_(.+)\Z/)
7219 {
7220 if($CppKeywords_A{$1}) {
7221 $Str=$1;
7222 }
7223 }
7224 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007225 }
7226 }
7227 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007228 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007229 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007230}
7231
7232sub getTreeStr($)
7233{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007234 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007235 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007236 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7237 {
7238 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007239 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007240 and $Str=~/\Ac99_(.+)\Z/)
7241 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007242 if($CppKeywords_A{$1}) {
7243 $Str=$1;
7244 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007245 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007246 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007247 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007248 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007249 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007250}
7251
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007252sub getFuncShortName($)
7253{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007254 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007255 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007256 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007257 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007258 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007259 {
7260 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7261 {
7262 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7263 return "operator ".$RName;
7264 }
7265 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007266 }
7267 else
7268 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007269 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7270 {
7271 if(my $Ind = $Operator_Indication{$1}) {
7272 return "operator".$Ind;
7273 }
7274 elsif(not $UnknownOperator{$1})
7275 {
7276 printMsg("WARNING", "unknown operator $1");
7277 $UnknownOperator{$1} = 1;
7278 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007279 }
7280 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007281 }
7282 else
7283 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007284 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7285 return getTreeStr($1);
7286 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007287 }
7288 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007289 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007290}
7291
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007292sub getFuncReturn($)
7293{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007294 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7295 {
7296 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7297 {
7298 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7299 return $1;
7300 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007301 }
7302 }
7303 return "";
7304}
7305
7306sub getFuncOrig($)
7307{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007308 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7309 {
7310 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7311 return $1;
7312 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007313 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007314 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007315}
7316
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007317sub unmangleArray(@)
7318{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007319 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007320 { # MSVC mangling
7321 my $UndNameCmd = get_CmdPath("undname");
7322 if(not $UndNameCmd) {
7323 exitStatus("Not_Found", "can't find \"undname\"");
7324 }
7325 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007326 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007327 }
7328 else
7329 { # GCC mangling
7330 my $CppFiltCmd = get_CmdPath("c++filt");
7331 if(not $CppFiltCmd) {
7332 exitStatus("Not_Found", "can't find c++filt in PATH");
7333 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007334 if(not defined $CPPFILT_SUPPORT_FILE)
7335 {
7336 my $Info = `$CppFiltCmd -h 2>&1`;
7337 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7338 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007339 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007340 if($CPPFILT_SUPPORT_FILE)
7341 { # new versions of c++filt can take a file
7342 if($#_>$MAX_CPPFILT_FILE_SIZE)
7343 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7344 # this is fixed in the oncoming version of Binutils
7345 my @Half = splice(@_, 0, ($#_+1)/2);
7346 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007347 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007348 else
7349 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007350 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7351 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7352 if($?==139)
7353 { # segmentation fault
7354 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7355 }
7356 return split(/\n/, $Res);
7357 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007358 }
7359 else
7360 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007361 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7362 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007363 my @Half = splice(@_, 0, ($#_+1)/2);
7364 return (unmangleArray(@Half), unmangleArray(@_))
7365 }
7366 else
7367 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007368 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007369 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7370 if($?==139)
7371 { # segmentation fault
7372 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7373 }
7374 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007375 }
7376 }
7377 }
7378}
7379
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007380sub get_ChargeLevel($$)
7381{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007382 my ($Symbol, $LibVersion) = @_;
7383 return "" if($Symbol!~/\A(_Z|\?)/);
7384 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7385 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007386 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007387 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007388 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007389 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007390 return "[in-charge]";
7391 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007392 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007393 return "[not-in-charge]";
7394 }
7395 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007396 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007397 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007398 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007399 return "[in-charge]";
7400 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007401 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007402 return "[not-in-charge]";
7403 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007404 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007405 return "[in-charge-deleting]";
7406 }
7407 }
7408 }
7409 else
7410 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007411 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007412 return "[in-charge]";
7413 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007414 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007415 return "[not-in-charge]";
7416 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007417 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007418 return "[in-charge]";
7419 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007420 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007421 return "[not-in-charge]";
7422 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007423 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007424 return "[in-charge-deleting]";
7425 }
7426 }
7427 return "";
7428}
7429
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007430sub get_Signature_M($$)
7431{
7432 my ($Symbol, $LibVersion) = @_;
7433 my $Signature_M = $tr_name{$Symbol};
7434 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7435 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007436 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007437 }
7438 return $Signature_M;
7439}
7440
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007441sub get_Signature($$)
7442{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007443 my ($Symbol, $LibVersion) = @_;
7444 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7445 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007446 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007447 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007448 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03007449
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007450 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7451 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007452 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007453 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7454 {
Andrey Ponomarenkoaef5cd12015-10-16 01:29:16 +03007455 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
7456 $ClassName=~s/\bstruct //g;
7457 $Signature .= $ClassName."::";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007458 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7459 $Signature .= "~";
7460 }
7461 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007462 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007463 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007464 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007465 }
7466 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007467 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007468 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007469 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7470 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007471 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007472 else
7473 {
7474 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007475 }
7476 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007477 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007478 {
7479 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007480 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007481 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007482 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007483 if(not $ParamTypeName) {
7484 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7485 }
7486 foreach my $Typedef (keys(%ChangedTypedef))
7487 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007488 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7489 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7490 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007491 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007492 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7493 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007494 if($ParamName eq "this"
7495 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007496 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007497 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007498 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007499 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007500 }
7501 else {
7502 push(@ParamArray, $ParamTypeName);
7503 }
7504 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007505 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7506 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007507 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007508 }
7509 else
7510 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007511 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007512 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007513 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007514 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007515 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007516 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7517 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007518 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007519 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007520 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7521 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007522 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007523 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007524 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7525 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007526 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007527 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007528 }
7529 }
7530 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007531 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007532 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007533 }
7534 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007535 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007536 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007537 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007538}
7539
7540sub create_member_decl($$)
7541{
7542 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007543 if($TName=~/\([\*]+\)/)
7544 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007545 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7546 return $TName;
7547 }
7548 else
7549 {
7550 my @ArraySizes = ();
7551 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7552 push(@ArraySizes, $1);
7553 }
7554 return $TName." ".$Member.join("", @ArraySizes);
7555 }
7556}
7557
7558sub getFuncType($)
7559{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007560 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7561 {
7562 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7563 {
7564 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7565 {
7566 if($Type eq "method_type") {
7567 return "Method";
7568 }
7569 elsif($Type eq "function_type") {
7570 return "Function";
7571 }
7572 else {
7573 return "Other";
7574 }
7575 }
7576 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007577 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007578 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007579}
7580
7581sub getFuncTypeId($)
7582{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007583 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7584 {
7585 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7586 return $1;
7587 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007588 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007589 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007590}
7591
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007592sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007593{ # "._N" or "$_N" in older GCC versions
7594 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007595}
7596
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007597sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007598{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007599 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7600 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007601 }
7602
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007603 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007604
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007605 if($_[1] ne "S")
7606 {
7607 $N=~s/\A[ ]+//g;
7608 $N=~s/[ ]+\Z//g;
7609 $N=~s/[ ]{2,}/ /g;
7610 }
7611
7612 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007613
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007614 $N=~s/\b(const|volatile) ([\w\:]+)([\*&,>]|\Z)/$2 $1$3/g; # "const void" to "void const"
7615
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007616 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007617
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007618 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7619 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007620
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007621 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007622
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007623 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007624
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007625 if($_[1] eq "S")
7626 {
7627 if(index($N, "operator")!=-1) {
7628 $N=~s/\b(operator[ ]*)> >/$1>>/;
7629 }
7630 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007631
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +03007632 $N=~s/,([^ ])/, $1/g;
Andrey Ponomarenko99640d32015-11-01 21:20:50 +03007633
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007634 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007635}
7636
7637sub get_HeaderDeps($$)
7638{
7639 my ($AbsPath, $LibVersion) = @_;
7640 return () if(not $AbsPath or not $LibVersion);
7641 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7642 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7643 }
7644 my %IncDir = ();
7645 detect_recursive_includes($AbsPath, $LibVersion);
7646 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7647 {
7648 next if(not $HeaderPath);
7649 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7650 my $Dir = get_dirname($HeaderPath);
7651 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7652 {
7653 my $Dep = $Dir;
7654 if($Prefix)
7655 {
7656 if($OSgroup eq "windows")
7657 { # case insensitive seach on windows
7658 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7659 next;
7660 }
7661 }
7662 elsif($OSgroup eq "macos")
7663 { # seach in frameworks
7664 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7665 {
7666 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7667 {# frameworks
7668 my ($HFramework, $HName) = ($1, $2);
7669 $Dep = $HFramework;
7670 }
7671 else
7672 {# mismatch
7673 next;
7674 }
7675 }
7676 }
7677 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7678 { # Linux, FreeBSD
7679 next;
7680 }
7681 }
7682 if(not $Dep)
7683 { # nothing to include
7684 next;
7685 }
7686 if(is_default_include_dir($Dep))
7687 { # included by the compiler
7688 next;
7689 }
7690 if(get_depth($Dep)==1)
7691 { # too short
7692 next;
7693 }
7694 if(isLibcDir($Dep))
7695 { # do NOT include /usr/include/{sys,bits}
7696 next;
7697 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007698 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007699 }
7700 }
7701 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7702 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7703}
7704
7705sub sortIncPaths($$)
7706{
7707 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007708 if(not $ArrRef or $#{$ArrRef}<0) {
7709 return $ArrRef;
7710 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007711 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7712 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007713 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007714 return $ArrRef;
7715}
7716
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007717sub sortDeps($$$)
7718{
7719 if($Header_Dependency{$_[2]}{$_[0]}
7720 and not $Header_Dependency{$_[2]}{$_[1]}) {
7721 return 1;
7722 }
7723 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7724 and $Header_Dependency{$_[2]}{$_[1]}) {
7725 return -1;
7726 }
7727 return 0;
7728}
7729
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007730sub join_P($$)
7731{
7732 my $S = "/";
7733 if($OSgroup eq "windows") {
7734 $S = "\\";
7735 }
7736 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007737}
7738
7739sub get_namespace_additions($)
7740{
7741 my $NameSpaces = $_[0];
7742 my ($Additions, $AddNameSpaceId) = ("", 1);
7743 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7744 {
7745 next if($SkipNameSpaces{$Version}{$NS});
7746 next if(not $NS or $NameSpaces->{$NS}==-1);
7747 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7748 next if($NS=~/\A__/i);
7749 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007750 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007751 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7752 my @NS_Parts = split(/::/, $NS);
7753 next if($#NS_Parts==-1);
7754 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7755 foreach my $NS_Part (@NS_Parts)
7756 {
7757 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7758 $TypeDecl_Suffix .= "}";
7759 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007760 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007761 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7762 $Additions.=" $TypeDecl\n $FuncDecl\n";
7763 $AddNameSpaceId+=1;
7764 }
7765 return $Additions;
7766}
7767
7768sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007769{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007770 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007771 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007772 if($Fmt eq "windows")
7773 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007774 $Path=~s/\//\\/g;
7775 $Path=lc($Path);
7776 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007777 else
7778 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007779 $Path=~s/\\/\//g;
7780 }
7781 return $Path;
7782}
7783
7784sub inc_opt($$)
7785{
7786 my ($Path, $Style) = @_;
7787 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007788 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007789 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007790 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007791 return "-I\"".path_format($Path, "unix")."\"";
7792 }
7793 elsif($OSgroup eq "macos"
7794 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007795 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007796 return "-F".esc(get_dirname($Path));
7797 }
7798 else {
7799 return "-I".esc($Path);
7800 }
7801 }
7802 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007803 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007804 }
7805 return "";
7806}
7807
7808sub platformSpecs($)
7809{
7810 my $LibVersion = $_[0];
7811 my $Arch = getArch($LibVersion);
7812 if($OStarget eq "symbian")
7813 { # options for GCCE compiler
7814 my %Symbian_Opts = map {$_=>1} (
7815 "-D__GCCE__",
7816 "-DUNICODE",
7817 "-fexceptions",
7818 "-D__SYMBIAN32__",
7819 "-D__MARM_INTERWORK__",
7820 "-D_UNICODE",
7821 "-D__S60_50__",
7822 "-D__S60_3X__",
7823 "-D__SERIES60_3X__",
7824 "-D__EPOC32__",
7825 "-D__MARM__",
7826 "-D__EABI__",
7827 "-D__MARM_ARMV5__",
7828 "-D__SUPPORT_CPP_EXCEPTIONS__",
7829 "-march=armv5t",
7830 "-mapcs",
7831 "-mthumb-interwork",
7832 "-DEKA2",
7833 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7834 );
7835 return join(" ", keys(%Symbian_Opts));
7836 }
7837 elsif($OSgroup eq "windows"
7838 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7839 { # add options to MinGW compiler
7840 # to simulate the MSVC compiler
7841 my %MinGW_Opts = map {$_=>1} (
7842 "-D_WIN32",
7843 "-D_STDCALL_SUPPORTED",
7844 "-D__int64=\"long long\"",
7845 "-D__int32=int",
7846 "-D__int16=short",
7847 "-D__int8=char",
7848 "-D__possibly_notnullterminated=\" \"",
7849 "-D__nullterminated=\" \"",
7850 "-D__nullnullterminated=\" \"",
7851 "-D__w64=\" \"",
7852 "-D__ptr32=\" \"",
7853 "-D__ptr64=\" \"",
7854 "-D__forceinline=inline",
7855 "-D__inline=inline",
7856 "-D__uuidof(x)=IID()",
7857 "-D__try=",
7858 "-D__except(x)=",
7859 "-D__declspec(x)=__attribute__((x))",
7860 "-D__pragma(x)=",
7861 "-D_inline=inline",
7862 "-D__forceinline=__inline",
7863 "-D__stdcall=__attribute__((__stdcall__))",
7864 "-D__cdecl=__attribute__((__cdecl__))",
7865 "-D__fastcall=__attribute__((__fastcall__))",
7866 "-D__thiscall=__attribute__((__thiscall__))",
7867 "-D_stdcall=__attribute__((__stdcall__))",
7868 "-D_cdecl=__attribute__((__cdecl__))",
7869 "-D_fastcall=__attribute__((__fastcall__))",
7870 "-D_thiscall=__attribute__((__thiscall__))",
7871 "-DSHSTDAPI_(x)=x",
7872 "-D_MSC_EXTENSIONS",
7873 "-DSECURITY_WIN32",
7874 "-D_MSC_VER=1500",
7875 "-D_USE_DECLSPECS_FOR_SAL",
7876 "-D__noop=\" \"",
7877 "-DDECLSPEC_DEPRECATED=\" \"",
7878 "-D__builtin_alignof(x)=__alignof__(x)",
7879 "-DSORTPP_PASS");
7880 if($Arch eq "x86") {
7881 $MinGW_Opts{"-D_M_IX86=300"}=1;
7882 }
7883 elsif($Arch eq "x86_64") {
7884 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7885 }
7886 elsif($Arch eq "ia64") {
7887 $MinGW_Opts{"-D_M_IA64=300"}=1;
7888 }
7889 return join(" ", keys(%MinGW_Opts));
7890 }
7891 return "";
7892}
7893
7894my %C_Structure = map {$_=>1} (
7895# FIXME: Can't separate union and struct data types before dumping,
7896# so it sometimes cause compilation errors for unknown reason
7897# when trying to declare TYPE* tmp_add_class_N
7898# This is a list of such structures + list of other C structures
7899 "sigval",
7900 "sigevent",
7901 "sigaction",
7902 "sigvec",
7903 "sigstack",
7904 "timeval",
7905 "timezone",
7906 "rusage",
7907 "rlimit",
7908 "wait",
7909 "flock",
7910 "stat",
7911 "_stat",
7912 "stat32",
7913 "_stat32",
7914 "stat64",
7915 "_stat64",
7916 "_stati64",
7917 "if_nameindex",
7918 "usb_device",
7919 "sigaltstack",
7920 "sysinfo",
7921 "timeLocale",
7922 "tcp_debug",
7923 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007924 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007925 "timespec",
7926 "random_data",
7927 "drand48_data",
7928 "_IO_marker",
7929 "_IO_FILE",
7930 "lconv",
7931 "sched_param",
7932 "tm",
7933 "itimerspec",
7934 "_pthread_cleanup_buffer",
7935 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007936 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007937 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007938 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007939 "sigcontext",
7940 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007941 # Mac
7942 "_timex",
7943 "_class_t",
7944 "_category_t",
7945 "_class_ro_t",
7946 "_protocol_t",
7947 "_message_ref_t",
7948 "_super_message_ref_t",
7949 "_ivar_t",
7950 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007951);
7952
7953sub getCompileCmd($$$)
7954{
7955 my ($Path, $Opt, $Inc) = @_;
7956 my $GccCall = $GCC_PATH;
7957 if($Opt) {
7958 $GccCall .= " ".$Opt;
7959 }
7960 $GccCall .= " -x ";
7961 if($OSgroup eq "macos") {
7962 $GccCall .= "objective-";
7963 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007964
7965 if($EMERGENCY_MODE_48)
7966 { # workaround for GCC 4.8 (C only)
7967 $GccCall .= "c++";
7968 }
7969 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007970 { # compile as "C++" header
7971 # to obtain complete dump using GCC 4.0
7972 $GccCall .= "c++-header";
7973 }
7974 else
7975 { # compile as "C++" source
7976 # GCC 3.3 cannot compile headers
7977 $GccCall .= "c++";
7978 }
7979 if(my $Opts = platformSpecs($Version))
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007980 { # platform-specific options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007981 $GccCall .= " ".$Opts;
7982 }
7983 # allow extra qualifications
7984 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007985 $GccCall .= " -fpermissive";
7986 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007987 if($NoStdInc)
7988 {
7989 $GccCall .= " -nostdinc";
7990 $GccCall .= " -nostdinc++";
7991 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007992 if(my $Opts_GCC = getGCC_Opts($Version))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007993 { # user-defined options
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +04007994 $GccCall .= " ".$Opts_GCC;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007995 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007996 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007997 if($Inc)
7998 { # include paths
7999 $GccCall .= " ".$Inc;
8000 }
8001 return $GccCall;
8002}
8003
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008004sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008005{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008006 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008007 my %HeaderElems = (
8008 # Types
8009 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008010 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008011 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8012 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008013 "time.h" => ["time_t"],
8014 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008015 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8016 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008017 "stdbool.h" => ["_Bool"],
8018 "rpc/xdr.h" => ["bool_t"],
8019 "in_systm.h" => ["n_long", "n_short"],
8020 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008021 "arpa/inet.h" => ["fw_src", "ip_src"],
8022 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008023 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008024 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008025 );
8026 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008027 foreach (keys(%HeaderElems))
8028 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008029 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008030 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008031 }
8032 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008033 my %Types = ();
8034 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8035 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008036 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008037 }
8038 if(keys(%Types))
8039 {
8040 my %AddHeaders = ();
8041 foreach my $Type (keys(%Types))
8042 {
8043 if(my $Header = $AutoPreamble{$Type})
8044 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008045 if(my $Path = identifyHeader($Header, $LibVersion))
8046 {
8047 if(skipHeader($Path, $LibVersion)) {
8048 next;
8049 }
8050 $Path = path_format($Path, $OSgroup);
8051 $AddHeaders{$Path}{"Type"} = $Type;
8052 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008053 }
8054 }
8055 }
8056 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008057 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008058 }
8059 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008060 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008061}
8062
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008063sub checkCTags($)
8064{
8065 my $Path = $_[0];
8066 if(not $Path) {
8067 return;
8068 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008069 my $CTags = undef;
8070
8071 if($OSgroup eq "bsd")
8072 { # use ectags on BSD
8073 $CTags = get_CmdPath("ectags");
8074 if(not $CTags) {
8075 printMsg("WARNING", "can't find \'ectags\' program");
8076 }
8077 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008078 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008079 $CTags = get_CmdPath("ctags");
8080 }
8081 if(not $CTags)
8082 {
8083 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008084 return;
8085 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008086
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008087 if($OSgroup ne "linux")
8088 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008089 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8090 if($Info!~/exuberant/i)
8091 {
8092 printMsg("WARNING", "incompatible version of \'ctags\' program");
8093 return;
8094 }
8095 }
8096
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008097 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008098 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008099 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008100 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008101 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008102 open(CTAGS, "<", $Out);
8103 while(my $Line = <CTAGS>)
8104 {
8105 chomp($Line);
8106 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008107 if(defined $Intrinsic_Keywords{$Name})
8108 { # noise
8109 next;
8110 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008111 if($Type eq "n")
8112 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008113 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008114 next;
8115 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008116 if(index($Scpe, "struct:")==0) {
8117 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008118 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008119 if(index($Scpe, "namespace:")==0)
8120 {
8121 if($Scpe=~s/\Anamespace://) {
8122 $Name = $Scpe."::".$Name;
8123 }
8124 }
8125 $TUnit_NameSpaces{$Version}{$Name} = 1;
8126 }
8127 elsif($Type eq "p")
8128 {
8129 if(not $Scpe or index($Scpe, "namespace:")==0) {
8130 $TUnit_Funcs{$Version}{$Name} = 1;
8131 }
8132 }
8133 elsif($Type eq "x")
8134 {
8135 if(not $Scpe or index($Scpe, "namespace:")==0) {
8136 $TUnit_Vars{$Version}{$Name} = 1;
8137 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008138 }
8139 }
8140 close(CTAGS);
8141}
8142
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008143sub preChange($$)
8144{
8145 my ($HeaderPath, $IncStr) = @_;
8146
8147 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8148 my $Content = undef;
8149
8150 if($OStarget eq "windows"
8151 and get_dumpmachine($GCC_PATH)=~/mingw/i
8152 and $MinGWMode{$Version}!=-1)
8153 { # modify headers to compile by MinGW
8154 if(not $Content)
8155 { # preprocessing
8156 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8157 }
8158 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8159 { # __asm { ... }
8160 $MinGWMode{$Version}=1;
8161 }
8162 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8163 { # comments after preprocessing
8164 $MinGWMode{$Version}=1;
8165 }
8166 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8167 { # 0xffui8
8168 $MinGWMode{$Version}=1;
8169 }
8170
8171 if($MinGWMode{$Version}) {
8172 printMsg("INFO", "Using MinGW compatibility mode");
8173 }
8174 }
8175
8176 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8177 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8178 { # rename C++ keywords in C code
8179 # disable this code by -cpp-compatible option
8180 if(not $Content)
8181 { # preprocessing
8182 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8183 }
8184 my $RegExp_C = join("|", keys(%CppKeywords_C));
8185 my $RegExp_F = join("|", keys(%CppKeywords_F));
8186 my $RegExp_O = join("|", keys(%CppKeywords_O));
8187
8188 my $Detected = undef;
8189
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008190 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 +04008191 { # MATCH:
8192 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008193 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008194 # unsigned private: 8;
8195 # DO NOT MATCH:
8196 # #pragma GCC visibility push(default)
8197 $CppMode{$Version} = 1;
8198 $Detected = "$1$2$3$4" if(not defined $Detected);
8199 }
8200 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8201 { # MATCH:
8202 # int delete(...);
8203 # int explicit(...);
8204 # DO NOT MATCH:
8205 # void operator delete(...)
8206 $CppMode{$Version} = 1;
8207 $Detected = "$1$2$3" if(not defined $Detected);
8208 }
8209 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8210 { # MATCH:
8211 # int bool;
8212 # DO NOT MATCH:
8213 # bool X;
8214 # return *this;
8215 # throw;
8216 $CppMode{$Version} = 1;
8217 $Detected = "$1$2$3" if(not defined $Detected);
8218 }
8219 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8220 { # MATCH:
8221 # int operator(...);
8222 # DO NOT MATCH:
8223 # int operator()(...);
8224 $CppMode{$Version} = 1;
8225 $Detected = "$1$2$3" if(not defined $Detected);
8226 }
8227 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8228 { # MATCH:
8229 # int foo(int operator);
8230 # int foo(int operator, int other);
8231 # DO NOT MATCH:
8232 # int operator,(...);
8233 $CppMode{$Version} = 1;
8234 $Detected = "$1$2$3" if(not defined $Detected);
8235 }
8236 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8237 { # MATCH:
8238 # int foo(gboolean *bool);
8239 # DO NOT MATCH:
8240 # void setTabEnabled(int index, bool);
8241 $CppMode{$Version} = 1;
8242 $Detected = "$1$2$3" if(not defined $Detected);
8243 }
8244 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8245 { # MATCH:
8246 # int foo(int* this);
8247 # int bar(int this);
8248 # int baz(int throw);
8249 # DO NOT MATCH:
8250 # foo(X, this);
8251 $CppMode{$Version} = 1;
8252 $Detected = "$1$2$3$4" if(not defined $Detected);
8253 }
8254 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8255 { # MATCH:
8256 # struct template {...};
8257 # extern template foo(...);
8258 $CppMode{$Version} = 1;
8259 $Detected = "$1$2" if(not defined $Detected);
8260 }
8261
8262 if($CppMode{$Version} == 1)
8263 {
8264 if($Debug)
8265 {
8266 $Detected=~s/\A\s+//g;
8267 printMsg("INFO", "Detected code: \"$Detected\"");
8268 }
8269 }
8270
8271 # remove typedef enum NAME NAME;
8272 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8273 my $N = 0;
8274 while($N<=$#FwdTypedefs-1)
8275 {
8276 my $S = $FwdTypedefs[$N];
8277 if($S eq $FwdTypedefs[$N+1])
8278 {
8279 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008280 $CppMode{$Version} = 1;
8281
8282 if($Debug) {
8283 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8284 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008285 }
8286 $N+=2;
8287 }
8288
8289 if($CppMode{$Version}==1) {
8290 printMsg("INFO", "Using C++ compatibility mode");
8291 }
8292 }
8293
8294 if($CppMode{$Version}==1
8295 or $MinGWMode{$Version}==1)
8296 {
8297 my $IPath = $TMP_DIR."/dump$Version.i";
8298 writeFile($IPath, $Content);
8299 return $IPath;
8300 }
8301
8302 return undef;
8303}
8304
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008305sub getDump()
8306{
8307 if(not $GCC_PATH) {
8308 exitStatus("Error", "internal error - GCC path is not set");
8309 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008310
8311 my @Headers = keys(%{$Registered_Headers{$Version}});
8312 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8313
8314 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8315
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008316 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008317 my $HeaderPath = $TmpHeaderPath;
8318
8319 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008320 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008321 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8322 {
8323 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008324 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008325 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008326 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008327 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8328 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008329 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008330 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008331 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008332 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8333 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8334 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008335 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008336 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008337
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008338 if($ExtraInfo)
8339 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008340 if($IncludeString) {
8341 writeFile($ExtraInfo."/include-string", $IncludeString);
8342 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008343 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8344 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008345
8346 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8347 {
8348 my $REDIR = "";
8349 foreach my $P1 (sort @Redirects) {
8350 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8351 }
8352 writeFile($ExtraInfo."/include-redirect", $REDIR);
8353 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008354 }
8355
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008356 if(not keys(%{$TargetHeaders{$Version}}))
8357 { # Target headers
8358 addTargetHeaders($Version);
8359 }
8360
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008361 # clean memory
8362 %RecursiveIncludes = ();
8363 %Header_Include_Prefix = ();
8364 %Header_Includes = ();
8365
8366 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008367 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008368 delete($Cache{"detect_header_includes"});
8369 delete($Cache{"selectSystemHeader"});
8370
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008371 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008372 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8373 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008374
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008375 if($ExtraInfo)
8376 { # extra information for other tools
8377 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8378 }
8379
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008380 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008381 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008382 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008383
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008384 if($COMMON_LANGUAGE{$Version} eq "C++") {
8385 checkCTags($Pre);
8386 }
8387
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008388 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8389 { # try to correct the preprocessor output
8390 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008391 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008392
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008393 if($COMMON_LANGUAGE{$Version} eq "C++")
8394 { # add classes and namespaces to the dump
8395 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008396 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008397 or $MinGWMode{$Version}==1) {
8398 $CHdump .= " -fpreprocessed";
8399 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008400 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008401 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008402 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008403 chdir($ORIG_DIR);
8404 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8405 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008406 my $Content = readFile($ClassDump);
8407 foreach my $ClassInfo (split(/\n\n/, $Content))
8408 {
8409 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8410 {
8411 my $CName = $1;
8412 next if($CName=~/\A(__|_objc_|_opaque_)/);
8413 $TUnit_NameSpaces{$Version}{$CName} = -1;
8414 if($CName=~/\A[\w:]+\Z/)
8415 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008416 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008417 }
8418 if($CName=~/(\w[\w:]*)::/)
8419 { # namespaces
8420 my $NS = $1;
8421 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8422 $TUnit_NameSpaces{$Version}{$NS} = 1;
8423 }
8424 }
8425 }
8426 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8427 { # read v-tables (advanced approach)
8428 my ($CName, $VTable) = ($1, $2);
8429 $ClassVTable_Content{$Version}{$CName} = $VTable;
8430 }
8431 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008432 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8433 { # add user-defined namespaces
8434 $TUnit_NameSpaces{$Version}{$NS} = 1;
8435 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008436 if($Debug)
8437 { # debug mode
8438 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008439 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008440 }
8441 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008442 }
8443
8444 # add namespaces and classes
8445 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8446 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008447 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008448 }
8449 # some GCC versions don't include class methods to the TU dump by default
8450 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008451 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008452 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8453 {
8454 next if($C_Structure{$CName});
8455 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008456 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008457 if(not $Force and $GCC_44
8458 and $OSgroup eq "linux")
8459 { # optimization for linux with GCC >= 4.4
8460 # disable this code by -force option
8461 if(index($CName, "::")!=-1)
8462 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008463 next;
8464 }
8465 }
8466 else
8467 {
8468 if($CName=~/\A(.+)::[^:]+\Z/
8469 and $TUnit_Classes{$Version}{$1})
8470 { # classes inside other classes
8471 next;
8472 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008473 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008474 if(defined $TUnit_Funcs{$Version}{$CName})
8475 { # the same name for a function and type
8476 next;
8477 }
8478 if(defined $TUnit_Vars{$Version}{$CName})
8479 { # the same name for a variable and type
8480 next;
8481 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008482 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8483 }
8484 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008485 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008486 }
8487 }
8488 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8489 # create TU dump
8490 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008491 if($UserLang eq "C") {
8492 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8493 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008494 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008495 or $MinGWMode{$Version}==1) {
8496 $TUdump .= " -fpreprocessed";
8497 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008498 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008499 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8500 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008501 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008502 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008503 if($?)
8504 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008505 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008506 { # try to recompile
8507 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008508 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008509 and index($Errors, "c99_")!=-1
8510 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008511 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008512 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008513
8514 if($Debug)
8515 {
8516 # printMsg("INFO", $Errors);
8517 }
8518
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008519 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008520 resetLogging($Version);
8521 $TMP_DIR = tempdir(CLEANUP=>1);
8522 return getDump();
8523 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008524 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008525 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008526 { # add auto preamble headers and try again
8527 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008528 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008529 foreach my $Num (0 .. $#Headers)
8530 {
8531 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008532 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8533 {
8534 push_U($Include_Preamble{$Version}, $Path);
8535 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008536 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008537 }
8538 resetLogging($Version);
8539 $TMP_DIR = tempdir(CLEANUP=>1);
8540 return getDump();
8541 }
8542 elsif($Cpp0xMode{$Version}!=-1
8543 and ($Errors=~/\Q-std=c++0x\E/
8544 or $Errors=~/is not a class or namespace/))
8545 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008546 if(check_gcc($GCC_PATH, "4.6"))
8547 {
8548 $Cpp0xMode{$Version}=-1;
8549 printMsg("INFO", "Enabling c++0x mode");
8550 resetLogging($Version);
8551 $TMP_DIR = tempdir(CLEANUP=>1);
8552 $CompilerOptions{$Version} .= " -std=c++0x";
8553 return getDump();
8554 }
8555 else {
8556 printMsg("WARNING", "Probably c++0x construction detected");
8557 }
8558
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008559 }
8560 elsif($MinGWMode{$Version}==1)
8561 { # disable MinGW mode and try again
8562 $MinGWMode{$Version}=-1;
8563 resetLogging($Version);
8564 $TMP_DIR = tempdir(CLEANUP=>1);
8565 return getDump();
8566 }
8567 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008568 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008569 else {
8570 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008571 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008572 printMsg("ERROR", "some errors occurred when compiling headers");
8573 printErrorLog($Version);
8574 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008575 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008576 }
8577 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008578 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008579 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008580
8581 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8582 return $TUs[0];
8583 }
8584 else
8585 {
8586 my $Msg = "can't compile header(s)";
8587 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8588 $Msg .= "\nDid you install G++?";
8589 }
8590 exitStatus("Cannot_Compile", $Msg);
8591 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008592}
8593
8594sub cmd_file($)
8595{
8596 my $Path = $_[0];
8597 return "" if(not $Path or not -e $Path);
8598 if(my $CmdPath = get_CmdPath("file")) {
8599 return `$CmdPath -b \"$Path\"`;
8600 }
8601 return "";
8602}
8603
8604sub getIncString($$)
8605{
8606 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008607 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008608 my $String = "";
8609 foreach (@{$ArrRef}) {
8610 $String .= " ".inc_opt($_, $Style);
8611 }
8612 return $String;
8613}
8614
8615sub getIncPaths(@)
8616{
8617 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008618 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008619 if($INC_PATH_AUTODETECT{$Version})
8620 { # auto-detecting dependencies
8621 my %Includes = ();
8622 foreach my $HPath (@HeaderPaths)
8623 {
8624 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8625 {
8626 if($Skip_Include_Paths{$Version}{$Dir}) {
8627 next;
8628 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008629 if($SystemRoot)
8630 {
8631 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8632 next;
8633 }
8634 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008635 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008636 }
8637 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008638 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008639 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008640 }
8641 }
8642 else
8643 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008644 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008645 }
8646 return \@IncPaths;
8647}
8648
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008649sub push_U($@)
8650{ # push unique
8651 if(my $Array = shift @_)
8652 {
8653 if(@_)
8654 {
8655 my %Exist = map {$_=>1} @{$Array};
8656 foreach my $Elem (@_)
8657 {
8658 if(not defined $Exist{$Elem})
8659 {
8660 push(@{$Array}, $Elem);
8661 $Exist{$Elem} = 1;
8662 }
8663 }
8664 }
8665 }
8666}
8667
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008668sub callPreprocessor($$$)
8669{
8670 my ($Path, $Inc, $LibVersion) = @_;
8671 return "" if(not $Path or not -f $Path);
8672 my $IncludeString=$Inc;
8673 if(not $Inc) {
8674 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8675 }
8676 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008677 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008678 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008679 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008680}
8681
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008682sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008683{ # native "find" is much faster than File::Find (~6x)
8684 # also the File::Find doesn't support --maxdepth N option
8685 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008686 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008687 return () if(not $Path or not -e $Path);
8688 if($OSgroup eq "windows")
8689 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008690 $Path = get_abs_path($Path);
8691 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +03008692 my $Cmd = "dir \"$Path\" /B /O";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008693 if($MaxDepth!=1) {
8694 $Cmd .= " /S";
8695 }
8696 if($Type eq "d") {
8697 $Cmd .= " /AD";
8698 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008699 elsif($Type eq "f") {
8700 $Cmd .= " /A-D";
8701 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008702 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008703 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008704 {
8705 if(not $UseRegex)
8706 { # FIXME: how to search file names in MS shell?
8707 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008708 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008709 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008710 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008711 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008712 }
8713 my @AbsPaths = ();
8714 foreach my $File (@Files)
8715 {
8716 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008717 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008718 }
8719 if($Type eq "f" and not -f $File)
8720 { # skip dirs
8721 next;
8722 }
8723 push(@AbsPaths, path_format($File, $OSgroup));
8724 }
8725 if($Type eq "d") {
8726 push(@AbsPaths, $Path);
8727 }
8728 return @AbsPaths;
8729 }
8730 else
8731 {
8732 my $FindCmd = get_CmdPath("find");
8733 if(not $FindCmd) {
8734 exitStatus("Not_Found", "can't find a \"find\" command");
8735 }
8736 $Path = get_abs_path($Path);
8737 if(-d $Path and -l $Path
8738 and $Path!~/\/\Z/)
8739 { # for directories that are symlinks
8740 $Path.="/";
8741 }
8742 my $Cmd = $FindCmd." \"$Path\"";
8743 if($MaxDepth) {
8744 $Cmd .= " -maxdepth $MaxDepth";
8745 }
8746 if($Type) {
8747 $Cmd .= " -type $Type";
8748 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008749 if($Name and not $UseRegex)
8750 { # wildcards
8751 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008752 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008753 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008754 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008755 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8756 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008757 my @Files = split(/\n/, $Res);
8758 if($Name and $UseRegex)
8759 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008760 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008761 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008762 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008763 }
8764}
8765
8766sub unpackDump($)
8767{
8768 my $Path = $_[0];
8769 return "" if(not $Path or not -e $Path);
8770 $Path = get_abs_path($Path);
8771 $Path = path_format($Path, $OSgroup);
8772 my ($Dir, $FileName) = separate_path($Path);
8773 my $UnpackDir = $TMP_DIR."/unpack";
8774 rmtree($UnpackDir);
8775 mkpath($UnpackDir);
8776 if($FileName=~s/\Q.zip\E\Z//g)
8777 { # *.zip
8778 my $UnzipCmd = get_CmdPath("unzip");
8779 if(not $UnzipCmd) {
8780 exitStatus("Not_Found", "can't find \"unzip\" command");
8781 }
8782 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008783 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008784 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008785 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008786 }
8787 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008788 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008789 if(not @Contents) {
8790 exitStatus("Error", "can't extract \'$Path\'");
8791 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008792 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008793 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008794 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008795 { # *.tar.gz
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +04008796 # *.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008797 if($OSgroup eq "windows")
8798 { # -xvzf option is not implemented in tar.exe (2003)
8799 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8800 my $TarCmd = get_CmdPath("tar");
8801 if(not $TarCmd) {
8802 exitStatus("Not_Found", "can't find \"tar\" command");
8803 }
8804 my $GzipCmd = get_CmdPath("gzip");
8805 if(not $GzipCmd) {
8806 exitStatus("Not_Found", "can't find \"gzip\" command");
8807 }
8808 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008809 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008810 if($?) {
8811 exitStatus("Error", "can't extract \'$Path\'");
8812 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008813 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008814 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008815 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008816 }
8817 chdir($ORIG_DIR);
8818 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008819 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008820 if(not @Contents) {
8821 exitStatus("Error", "can't extract \'$Path\'");
8822 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008823 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008824 }
8825 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008826 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008827 my $TarCmd = get_CmdPath("tar");
8828 if(not $TarCmd) {
8829 exitStatus("Not_Found", "can't find \"tar\" command");
8830 }
8831 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008832 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008833 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008834 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008835 }
8836 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008837 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008838 if(not @Contents) {
8839 exitStatus("Error", "can't extract \'$Path\'");
8840 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008841 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008842 }
8843 }
8844}
8845
8846sub createArchive($$)
8847{
8848 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008849 if(not $To) {
8850 $To = ".";
8851 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008852 if(not $Path or not -e $Path
8853 or not -d $To) {
8854 return "";
8855 }
8856 my ($From, $Name) = separate_path($Path);
8857 if($OSgroup eq "windows")
8858 { # *.zip
8859 my $ZipCmd = get_CmdPath("zip");
8860 if(not $ZipCmd) {
8861 exitStatus("Not_Found", "can't find \"zip\"");
8862 }
8863 my $Pkg = $To."/".$Name.".zip";
8864 unlink($Pkg);
8865 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008866 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008867 if($?)
8868 { # cannot allocate memory (or other problems with "zip")
8869 unlink($Path);
8870 exitStatus("Error", "can't pack the ABI dump: ".$!);
8871 }
8872 chdir($ORIG_DIR);
8873 unlink($Path);
8874 return $Pkg;
8875 }
8876 else
8877 { # *.tar.gz
8878 my $TarCmd = get_CmdPath("tar");
8879 if(not $TarCmd) {
8880 exitStatus("Not_Found", "can't find \"tar\"");
8881 }
8882 my $GzipCmd = get_CmdPath("gzip");
8883 if(not $GzipCmd) {
8884 exitStatus("Not_Found", "can't find \"gzip\"");
8885 }
8886 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8887 unlink($Pkg);
8888 chdir($From);
8889 system($TarCmd, "-czf", $Pkg, $Name);
8890 if($?)
8891 { # cannot allocate memory (or other problems with "tar")
8892 unlink($Path);
8893 exitStatus("Error", "can't pack the ABI dump: ".$!);
8894 }
8895 chdir($ORIG_DIR);
8896 unlink($Path);
8897 return $To."/".$Name.".tar.gz";
8898 }
8899}
8900
8901sub is_header_file($)
8902{
8903 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8904 return $_[0];
8905 }
8906 return 0;
8907}
8908
8909sub is_not_header($)
8910{
8911 if($_[0]=~/\.\w+\Z/
8912 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8913 return 1;
8914 }
8915 return 0;
8916}
8917
8918sub is_header($$$)
8919{
8920 my ($Header, $UserDefined, $LibVersion) = @_;
8921 return 0 if(-d $Header);
8922 if(-f $Header) {
8923 $Header = get_abs_path($Header);
8924 }
8925 else
8926 {
8927 if(is_abs($Header))
8928 { # incorrect absolute path
8929 return 0;
8930 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008931 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008932 $Header = $HPath;
8933 }
8934 else
8935 { # can't find header
8936 return 0;
8937 }
8938 }
8939 if($Header=~/\.\w+\Z/)
8940 { # have an extension
8941 return is_header_file($Header);
8942 }
8943 else
8944 {
8945 if($UserDefined==2)
8946 { # specified on the command line
8947 if(cmd_file($Header)!~/HTML|XML/i) {
8948 return $Header;
8949 }
8950 }
8951 elsif($UserDefined)
8952 { # specified in the XML-descriptor
8953 # header file without an extension
8954 return $Header;
8955 }
8956 else
8957 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008958 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008959 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008960 { # !~/HTML|XML|shared|dynamic/i
8961 return $Header;
8962 }
8963 }
8964 }
8965 return 0;
8966}
8967
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008968sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008969{
8970 my $LibVersion = $_[0];
8971 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
8972 {
8973 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008974 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008975
8976 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
8977 detect_recursive_includes($RegHeader, $LibVersion);
8978 }
8979
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008980 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
8981 {
8982 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008983
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04008984 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008985 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
8986 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008987 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008988 }
8989 }
8990 }
8991}
8992
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008993sub familiarDirs($$)
8994{
8995 my ($D1, $D2) = @_;
8996 if($D1 eq $D2) {
8997 return 1;
8998 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04008999
9000 my $U1 = index($D1, "/usr/");
9001 my $U2 = index($D2, "/usr/");
9002
9003 if($U1==0 and $U2!=0) {
9004 return 0;
9005 }
9006
9007 if($U2==0 and $U1!=0) {
9008 return 0;
9009 }
9010
9011 if(index($D2, $D1."/")==0) {
9012 return 1;
9013 }
9014
9015 # /usr/include/DIR
9016 # /home/user/DIR
9017
9018 my $DL = get_depth($D1);
9019
9020 my @Dirs1 = ($D1);
9021 while($DL - get_depth($D1)<=2
9022 and get_depth($D1)>=4
9023 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9024 push(@Dirs1, $D1);
9025 }
9026
9027 my @Dirs2 = ($D2);
9028 while(get_depth($D2)>=4
9029 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9030 push(@Dirs2, $D2);
9031 }
9032
9033 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009034 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009035 foreach my $P2 (@Dirs2)
9036 {
9037
9038 if($P1 eq $P2) {
9039 return 1;
9040 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009041 }
9042 }
9043 return 0;
9044}
9045
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009046sub readHeaders($)
9047{
9048 $Version = $_[0];
9049 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9050 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009051 if($Debug)
9052 { # debug mode
9053 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009054 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009055 }
9056 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009057}
9058
9059sub prepareTypes($)
9060{
9061 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009062 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009063 { # support for old ABI dumps
9064 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009065 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009066 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009067 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9068 if($TName=~/\A(\w+)::(\w+)/) {
9069 my ($P1, $P2) = ($1, $2);
9070 if($P1 eq $P2) {
9071 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009072 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009073 else {
9074 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9075 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009076 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009077 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009078 }
9079 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009080 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009081 { # support for old ABI dumps
9082 # V < 2.5: array size == "number of elements"
9083 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009084 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009085 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009086 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009087 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009088 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009089 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009090 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009091 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009092 $Size *= $Base{"Size"};
9093 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009094 }
9095 else
9096 { # array[] is a pointer
9097 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009098 }
9099 }
9100 }
9101 }
9102 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009103 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009104 { # support for old ABI dumps
9105 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009106 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009107 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009108 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009109 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009110 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009111 my %Type = get_Type($TypeId, $LibVersion);
9112 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9113 my %Type2 = get_Type($TypeId_2, $V2);
9114 if($Type{"Size"} ne $Type2{"Size"}) {
9115 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009116 }
9117 }
9118 }
9119 }
9120}
9121
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009122sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009123{
9124 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009125
9126 if(not keys(%{$SymbolInfo{$LibVersion}}))
9127 { # check if input is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009128 if(not $ExtendedCheck)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009129 {
9130 if($CheckHeadersOnly) {
9131 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9132 }
9133 else {
9134 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9135 }
9136 }
9137 }
9138
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009139 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009140 if(not checkDump(1, "2.10")
9141 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009142 { # different formats
9143 $Remangle = 1;
9144 }
9145 if($CheckHeadersOnly)
9146 { # different languages
9147 if($UserLang)
9148 { # --lang=LANG for both versions
9149 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9150 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9151 {
9152 if($UserLang eq "C++")
9153 { # remangle symbols
9154 $Remangle = 1;
9155 }
9156 elsif($UserLang eq "C")
9157 { # remove mangling
9158 $Remangle = -1;
9159 }
9160 }
9161 }
9162 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009163
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009164 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009165 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009166 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009167 { # support for old ABI dumps
9168 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9169 {
9170 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9171 {
9172 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9173 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009174 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009175 if(defined $DVal and $DVal ne "")
9176 {
9177 if($TName eq "char") {
9178 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9179 }
9180 elsif($TName eq "bool") {
9181 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9182 }
9183 }
9184 }
9185 }
9186 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009187 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009188 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009189 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9190 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009191 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009192 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9193 # + support for old ABI dumps
9194 next;
9195 }
9196 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009197 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009198 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009199 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009200 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009201
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009202 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009203 if(not checkDump(1, "2.12")
9204 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009205 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009206 if($ShortName eq "operator>>")
9207 {
9208 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9209 { # corrected mangling of operator>>
9210 $SRemangle = 1;
9211 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009212 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009213 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9214 {
9215 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9216 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9217 { # corrected mangling of const global data
9218 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9219 # and incorrectly mangled by old ACC versions
9220 $SRemangle = 1;
9221 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009222 }
9223 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009224 if(not $CheckHeadersOnly)
9225 { # support for old ABI dumps
9226 if(not checkDump(1, "2.17")
9227 or not checkDump(2, "2.17"))
9228 {
9229 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9230 {
9231 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9232 {
9233 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9234 {
9235 $MnglName = $ShortName;
9236 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9237 }
9238 }
9239 }
9240 }
9241 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009242 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009243 { # support for old ABI dumps: some symbols are not mangled in old dumps
9244 # mangle both sets of symbols (old and new)
9245 # NOTE: remangling all symbols by the same mangler
9246 if($MnglName=~/\A_ZN(V|)K/)
9247 { # mangling may be incorrect on old ABI dumps
9248 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009249 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009250 }
9251 if($MnglName=~/\A_ZN(K|)V/)
9252 { # mangling may be incorrect on old ABI dumps
9253 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009254 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009255 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009256 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9257 or (not $ClassID and $CheckHeadersOnly)
9258 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9259 { # support for old ABI dumps, GCC >= 4.0
9260 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009261 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009262 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009263 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009264 $MangledNames{$LibVersion}{$MnglName} = 1;
9265 }
9266 }
9267 }
9268 elsif($Remangle==-1)
9269 { # remove mangling
9270 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009271 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009272 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009273 if(not $MnglName) {
9274 next;
9275 }
9276 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9277 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009278 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9279
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009280 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009281 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009282 { # support for old dumps
9283 # add "Volatile" attribute
9284 if($MnglName=~/_Z(K|)V/) {
9285 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9286 }
9287 }
9288 # symbol and its symlink have same signatures
9289 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009290 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009291 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009292
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009293 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9294 {
9295 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9296 if($SymVer{$LibVersion}{$Alias}) {
9297 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9298 }
9299 }
9300
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009301 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009302 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009303 }
9304 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9305 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9306 }
9307 if($ExtendedCheck)
9308 { # --ext option
9309 addExtension($LibVersion);
9310 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009311
9312 # clean memory
9313 delete($SymbolInfo{$LibVersion});
9314
9315 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009316 { # detect allocable classes with public exported constructors
9317 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009318 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009319 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009320 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009321 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009322 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9323 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009324 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009325 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009326 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009327 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009328 $AllocableClass{$LibVersion}{$ClassName} = 1;
9329 }
9330 }
9331 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009332 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009333 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009334 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009335 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009336 if($CheckHeadersOnly)
9337 {
9338 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9339 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9340 { # all symbols except non-virtual inline
9341 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9342 }
9343 }
9344 else {
9345 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009346 }
9347 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009348 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009349 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009350 }
9351 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009352 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009353 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009354 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009355 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009356 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009357 if(defined $Base{"Type"}
9358 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009359 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009360 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009361 if($Name=~/<([^<>\s]+)>/)
9362 {
9363 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9364 $ReturnedClass{$LibVersion}{$Tid} = 1;
9365 }
9366 }
9367 else {
9368 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9369 }
9370 }
9371 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009372 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009373 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009374 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009375 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009376 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009377 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009378 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009379 if($Base{"Type"}=~/Struct|Class/)
9380 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009381 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009382 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9383 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009384 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009385 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009386 }
9387 }
9388 }
9389 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009390
9391 # mapping {short name => symbols}
9392 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009393 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009394 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009395 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009396 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009397 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009398 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009399 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009400 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9401 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009402 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009403 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009404 }
9405 }
9406 }
9407 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009408
9409 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009410 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009411 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009412 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009413 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009414 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9415 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009416 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009417 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009418 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009419 $ClassNames{$LibVersion}{$TName} = 1;
9420 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009421 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009422 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9423 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009424 }
9425 }
9426 }
9427 }
9428 }
9429}
9430
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009431sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009432{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009433 my ($Tid, $LibVersion) = @_;
9434 if(not $Tid) {
9435 return $Tid;
9436 }
9437
9438 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9439 {
9440 if($TName_Tid{$LibVersion}{$Name}) {
9441 return $TName_Tid{$LibVersion}{$Name};
9442 }
9443 }
9444
9445 return $Tid;
9446}
9447
9448sub register_SymbolUsage($$$)
9449{
9450 my ($InfoId, $UsedType, $LibVersion) = @_;
9451
9452 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9453 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9454 {
9455 register_TypeUsage($RTid, $UsedType, $LibVersion);
9456 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9457 }
9458 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9459 {
9460 register_TypeUsage($FCid, $UsedType, $LibVersion);
9461 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9462
9463 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9464 { # register "this" pointer
9465 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9466 }
9467 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9468 { # register "this" pointer (const method)
9469 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9470 }
9471 }
9472 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9473 {
9474 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9475 {
9476 register_TypeUsage($PTid, $UsedType, $LibVersion);
9477 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9478 }
9479 }
9480 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9481 {
9482 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9483 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9484 register_TypeUsage($TTid, $UsedType, $LibVersion);
9485 }
9486 }
9487}
9488
9489sub register_TypeUsage($$$)
9490{
9491 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009492 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009493 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009494 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009495 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009496 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009497 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009498 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009499
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009500 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009501 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009502 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009503 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009504 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009505 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9506 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9507 }
9508 }
9509
9510 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9511 {
9512 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009513 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009514 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009515 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9516 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009517 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009518 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9519 {
9520 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9521 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009522 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009523 }
9524 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009525 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009526 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009527 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009528 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9529 {
9530 register_TypeUsage($MTid, $UsedType, $LibVersion);
9531 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009532 }
9533 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009534 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009535 or $TInfo{"Type"} eq "MethodPtr"
9536 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009537 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009538 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009539 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009540 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009541 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009542 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009543 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9544 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009545 }
9546 }
9547 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009548 if($TInfo{"Type"} eq "FieldPtr")
9549 {
9550 if(my $RTid = $TInfo{"Return"}) {
9551 register_TypeUsage($RTid, $UsedType, $LibVersion);
9552 }
9553 if(my $CTid = $TInfo{"Class"}) {
9554 register_TypeUsage($CTid, $UsedType, $LibVersion);
9555 }
9556 }
9557 if($TInfo{"Type"} eq "MethodPtr")
9558 {
9559 if(my $CTid = $TInfo{"Class"}) {
9560 register_TypeUsage($CTid, $UsedType, $LibVersion);
9561 }
9562 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009563 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009564 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009565 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009566 $UsedType->{$TypeId} = 1;
9567 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9568 {
9569 register_TypeUsage($BTid, $UsedType, $LibVersion);
9570 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9571 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009572 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009573 else
9574 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9575 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009576 }
9577 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009578}
9579
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009580sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009581{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009582 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9583
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009584 if($Level eq "Dump")
9585 {
9586 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9587 { # TODO: check if this symbol is from
9588 # base classes of other target symbols
9589 return 1;
9590 }
9591 }
9592
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009593 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9594 { # stdc++ interfaces
9595 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009596 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009597
9598 my $Target = 0;
9599 if(my $Header = $SInfo->{"Header"}) {
9600 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9601 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009602 if($ExtendedCheck)
9603 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009604 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009605 $Target = 1;
9606 }
9607 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009608 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009609 {
9610 if($Target)
9611 {
9612 if($Level eq "Dump")
9613 { # dumped
9614 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009615 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009616 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009617 return 1;
9618 }
9619 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009620 else {
9621 return 1;
9622 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009623 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009624 elsif($Level eq "Source")
9625 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009626 return 1;
9627 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009628 elsif($Level eq "Binary")
9629 { # checked
9630 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9631 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9632 return 1;
9633 }
9634 }
9635 }
9636 }
9637 else
9638 { # library is available
9639 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9640 { # exported symbols
9641 return 1;
9642 }
9643 if($Level eq "Dump")
9644 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009645 if($BinaryOnly)
9646 {
9647 if($SInfo->{"Data"})
9648 {
9649 if($Target) {
9650 return 1;
9651 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009652 }
9653 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009654 else
9655 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009656 if($Target) {
9657 return 1;
9658 }
9659 }
9660 }
9661 elsif($Level eq "Source")
9662 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009663 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +03009664 or isInLineInst($SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009665 { # skip LOCAL symbols
9666 if($Target) {
9667 return 1;
9668 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009669 }
9670 }
9671 elsif($Level eq "Binary")
9672 { # checked
9673 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9674 {
9675 if($Target) {
9676 return 1;
9677 }
9678 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009679 }
9680 }
9681 return 0;
9682}
9683
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009684sub cleanDump($)
9685{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009686 my $LibVersion = $_[0];
9687 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9688 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009689 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9690 {
9691 delete($SymbolInfo{$LibVersion}{$InfoId});
9692 next;
9693 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009694 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009695 if(not $MnglName)
9696 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009697 delete($SymbolInfo{$LibVersion}{$InfoId});
9698 next;
9699 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009700 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009701 if(not $ShortName)
9702 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009703 delete($SymbolInfo{$LibVersion}{$InfoId});
9704 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009705 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009706 if($MnglName eq $ShortName)
9707 { # remove duplicate data
9708 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009709 }
9710 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9711 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9712 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009713 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9714 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9715 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009716 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009717 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009718 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009719 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009720 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9721 {
9722 delete($TypeInfo{$LibVersion}{$Tid});
9723 next;
9724 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009725 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009726 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009727 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009728 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9729 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9730 }
9731 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009732 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9733 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9734 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009735 }
9736}
9737
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009738sub pickType($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009739{
9740 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009741
9742 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9743 {
9744 if(defined $TypeInfo{$LibVersion}{$Dupl})
9745 {
9746 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9747 { # duplicate
9748 return 0;
9749 }
9750 }
9751 }
9752
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009753 my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"};
9754
9755 if(isBuiltIn($THeader)) {
9756 return 0;
9757 }
9758
9759 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/) {
9760 return 0;
9761 }
9762
9763 if(isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"})) {
9764 return 0;
9765 }
9766
9767 if(selfTypedef($Tid, $LibVersion)) {
9768 return 0;
9769 }
9770
9771 if(not isTargetType($Tid, $LibVersion)) {
9772 return 0;
9773 }
9774
9775 return 0;
9776}
9777
9778sub isTargetType($$)
9779{
9780 my ($Tid, $LibVersion) = @_;
9781
9782 if($TypeInfo{$LibVersion}{$Tid}{"Type"}!~/Class|Struct|Union|Enum|Typedef/)
9783 { # derived
9784 return 1;
9785 }
9786
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009787 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9788 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009789 if(not is_target_header($THeader, $LibVersion))
9790 { # from target headers
9791 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009792 }
9793 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +03009794 else {
9795 return 0;
9796 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009797
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +03009798 if($SkipInternalTypes)
9799 {
9800 if($TypeInfo{$LibVersion}{$Tid}{"Name"}=~/($SkipInternalTypes)/)
9801 {
9802 return 0;
9803 }
9804 }
9805
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009806 return 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009807}
9808
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009809sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009810{ # remove unused data types from the ABI dump
9811 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009812
9813 my %UsedType = ();
9814
9815 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009816 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009817 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009818 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009819 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009820 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009821 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009822 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009823 next;
9824 }
9825
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009826 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009827 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +03009828 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009829 {
9830 my %Tree = ();
9831 register_TypeUsage($Tid, \%Tree, $LibVersion);
9832
9833 my $Tmpl = 0;
9834 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9835 {
9836 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9837 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9838 {
9839 $Tmpl = 1;
9840 last;
9841 }
9842 }
9843 if(not $Tmpl)
9844 {
9845 foreach (keys(%Tree)) {
9846 $UsedType{$_} = 1;
9847 }
9848 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009849 }
9850 }
9851 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009852
9853 my %Delete = ();
9854
9855 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009856 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009857 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009858 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009859 next;
9860 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009861
9862 if($Kind eq "Extra")
9863 {
9864 my %Tree = ();
9865 register_TypeUsage($Tid, \%Tree, $LibVersion);
9866
9867 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9868 {
9869 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9870 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9871 {
9872 $Delete{$Tid} = 1;
9873 last;
9874 }
9875 }
9876 }
9877 else
9878 {
9879 # remove type
9880 delete($TypeInfo{$LibVersion}{$Tid});
9881 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009882 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009883
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009884 if($Kind eq "Extra")
9885 { # remove duplicates
9886 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9887 {
9888 if($UsedType{$Tid})
9889 { # All & Extended
9890 next;
9891 }
9892
9893 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9894
9895 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9896 delete($TypeInfo{$LibVersion}{$Tid});
9897 }
9898 }
9899 }
9900
9901 foreach my $Tid (keys(%Delete))
9902 {
9903 delete($TypeInfo{$LibVersion}{$Tid});
9904 }
9905}
9906
9907sub check_Completeness($$)
9908{
9909 my ($Info, $LibVersion) = @_;
9910
9911 # data types
9912 if(defined $Info->{"Memb"})
9913 {
9914 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9915 {
9916 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9917 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9918 }
9919 }
9920 }
9921 if(defined $Info->{"Base"})
9922 {
9923 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9924 check_TypeInfo($Bid, $LibVersion);
9925 }
9926 }
9927 if(defined $Info->{"BaseType"}) {
9928 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9929 }
9930 if(defined $Info->{"TParam"})
9931 {
9932 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9933 {
9934 my $TName = $Info->{"TParam"}{$Pos}{"name"};
9935 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
9936 next;
9937 }
9938 if($TName eq "_BoolType") {
9939 next;
9940 }
9941 if($TName=~/\Asizeof\(/) {
9942 next;
9943 }
9944 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
9945 check_TypeInfo($Tid, $LibVersion);
9946 }
9947 else
9948 {
9949 if(defined $Debug) {
9950 printMsg("WARNING", "missed type $TName");
9951 }
9952 }
9953 }
9954 }
9955
9956 # symbols
9957 if(defined $Info->{"Param"})
9958 {
9959 foreach my $Pos (keys(%{$Info->{"Param"}}))
9960 {
9961 if(defined $Info->{"Param"}{$Pos}{"type"}) {
9962 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
9963 }
9964 }
9965 }
9966 if(defined $Info->{"Return"}) {
9967 check_TypeInfo($Info->{"Return"}, $LibVersion);
9968 }
9969 if(defined $Info->{"Class"}) {
9970 check_TypeInfo($Info->{"Class"}, $LibVersion);
9971 }
9972}
9973
9974sub check_TypeInfo($$)
9975{
9976 my ($Tid, $LibVersion) = @_;
9977
9978 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
9979 return;
9980 }
9981 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
9982
9983 if(defined $TypeInfo{$LibVersion}{$Tid})
9984 {
9985 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
9986 printMsg("ERROR", "missed type name ($Tid)");
9987 }
9988 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
9989 }
9990 else {
9991 printMsg("ERROR", "missed type id $Tid");
9992 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009993}
9994
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009995sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009996{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009997 my ($TypeId, $LibVersion) = @_;
9998 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009999 if($Type{"Type"} eq "Typedef")
10000 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010001 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010002 if($Base{"Type"}=~/Class|Struct/)
10003 {
10004 if($Type{"Name"} eq $Base{"Name"}) {
10005 return 1;
10006 }
10007 elsif($Type{"Name"}=~/::(\w+)\Z/)
10008 {
10009 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10010 { # QPointer<QWidget>::QPointer
10011 return 1;
10012 }
10013 }
10014 }
10015 }
10016 return 0;
10017}
10018
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010019sub addExtension($)
10020{
10021 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010022 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010023 {
Andrey Ponomarenko28874762015-08-28 21:59:28 +030010024 if(pickType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010025 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010026 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10027 $TName=~s/\A(struct|union|class|enum) //;
10028 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010029
10030 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10031 "Header" => "extended.h",
10032 "ShortName" => $Symbol,
10033 "MnglName" => $Symbol,
10034 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10035 );
10036
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010037 $ExtendedSymbols{$Symbol} = 1;
10038 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10039 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010040 }
10041 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010042 $ExtendedSymbols{"external_func_0"} = 1;
10043 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10044 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010045}
10046
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010047sub findMethod($$$)
10048{
10049 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010050 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010051 {
10052 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10053 return $VirtMethodInClass;
10054 }
10055 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10056 return $VirtMethodInBaseClasses;
10057 }
10058 }
10059 return "";
10060}
10061
10062sub findMethod_Class($$$)
10063{
10064 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010065 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010066 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10067 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10068 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10069 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10070 { # search for interface with the same parameters suffix (overridden)
10071 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10072 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010073 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10074 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010075 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10076 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010077 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10078 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10079 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10080 return $Candidate;
10081 }
10082 }
10083 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010084 else
10085 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010086 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10087 return $Candidate;
10088 }
10089 }
10090 }
10091 }
10092 return "";
10093}
10094
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010095sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010096{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010097 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010098 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010099 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010100 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10101 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010102 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010103 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010104 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010105 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10106 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010107 { # pure virtual D2-destructors are marked as "virt" in the dump
10108 # virtual D2-destructors are NOT marked as "virt" in the dump
10109 # both destructors are not presented in the v-table
10110 next;
10111 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010112 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010113 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10114 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010115 }
10116}
10117
10118sub registerOverriding($)
10119{
10120 my $LibVersion = $_[0];
10121 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010122 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010123 foreach my $ClassName (@Classes)
10124 {
10125 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10126 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010127 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10128 { # pure virtuals
10129 next;
10130 }
10131 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10132 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010133 {
10134 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10135 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10136 { # both overridden virtual methods
10137 # and implemented pure virtual methods
10138 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10139 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10140 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10141 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010142 }
10143 }
10144 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10145 delete($VirtualTable{$LibVersion}{$ClassName});
10146 }
10147 }
10148}
10149
10150sub setVirtFuncPositions($)
10151{
10152 my $LibVersion = $_[0];
10153 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10154 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010155 my ($Num, $Rel) = (1, 0);
10156
10157 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010158 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010159 if($UsedDump{$LibVersion}{"DWARF"}) {
10160 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10161 }
10162 else {
10163 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10164 }
10165 foreach my $VirtFunc (@Funcs)
10166 {
10167 if($UsedDump{$LibVersion}{"DWARF"}) {
10168 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10169 }
10170 else {
10171 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10172 }
10173
10174 # set relative positions
10175 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10176 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10177 { # relative position excluding added and removed virtual functions
10178 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10179 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10180 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10181 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010182 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010183 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010184 }
10185 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010186 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010187 {
10188 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010189 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010190 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010191 }
10192 }
10193}
10194
10195sub get_sub_classes($$$)
10196{
10197 my ($ClassId, $LibVersion, $Recursive) = @_;
10198 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10199 my @Subs = ();
10200 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10201 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010202 if($Recursive)
10203 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010204 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10205 push(@Subs, $SubSubId);
10206 }
10207 }
10208 push(@Subs, $SubId);
10209 }
10210 return @Subs;
10211}
10212
10213sub get_base_classes($$$)
10214{
10215 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010216 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010217 return () if(not defined $ClassType{"Base"});
10218 my @Bases = ();
10219 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10220 keys(%{$ClassType{"Base"}}))
10221 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010222 if($Recursive)
10223 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010224 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10225 push(@Bases, $SubBaseId);
10226 }
10227 }
10228 push(@Bases, $BaseId);
10229 }
10230 return @Bases;
10231}
10232
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010233sub getVTable_Model($$)
10234{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010235 my ($ClassId, $LibVersion) = @_;
10236 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10237 my @Elements = ();
10238 foreach my $BaseId (@Bases, $ClassId)
10239 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010240 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010241 {
10242 if(defined $VirtualTable{$LibVersion}{$BName})
10243 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010244 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10245 if($UsedDump{$LibVersion}{"DWARF"}) {
10246 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10247 }
10248 else {
10249 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10250 }
10251 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010252 push(@Elements, $VFunc);
10253 }
10254 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010255 }
10256 }
10257 return @Elements;
10258}
10259
10260sub getVShift($$)
10261{
10262 my ($ClassId, $LibVersion) = @_;
10263 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10264 my $VShift = 0;
10265 foreach my $BaseId (@Bases)
10266 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010267 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010268 {
10269 if(defined $VirtualTable{$LibVersion}{$BName}) {
10270 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10271 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010272 }
10273 }
10274 return $VShift;
10275}
10276
10277sub getShift($$)
10278{
10279 my ($ClassId, $LibVersion) = @_;
10280 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10281 my $Shift = 0;
10282 foreach my $BaseId (@Bases)
10283 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010284 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010285 {
10286 if($Size!=1)
10287 { # not empty base class
10288 $Shift+=$Size;
10289 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010290 }
10291 }
10292 return $Shift;
10293}
10294
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010295sub getVTable_Size($$)
10296{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010297 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010298 my $Size = 0;
10299 # three approaches
10300 if(not $Size)
10301 { # real size
10302 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10303 $Size = keys(%VTable);
10304 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010305 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010306 if(not $Size)
10307 { # shared library symbol size
10308 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10309 $Size /= $WORD_SIZE{$LibVersion};
10310 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010311 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010312 if(not $Size)
10313 { # model size
10314 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10315 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10316 }
10317 }
10318 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010319}
10320
10321sub isCopyingClass($$)
10322{
10323 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010324 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010325}
10326
10327sub isLeafClass($$)
10328{
10329 my ($ClassId, $LibVersion) = @_;
10330 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10331}
10332
10333sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010334{ # check structured type for public fields
10335 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010336}
10337
10338sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010339{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010340 my ($TypePtr, $Skip, $Start, $End) = @_;
10341 return 0 if(not $TypePtr);
10342 if($End==-1) {
10343 $End = keys(%{$TypePtr->{"Memb"}})-1;
10344 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030010345 foreach my $MemPos (sort {int($a)<=>int($b)} keys(%{$TypePtr->{"Memb"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010346 {
10347 if($Skip and $Skip->{$MemPos})
10348 { # skip removed/added fields
10349 next;
10350 }
10351 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10352 {
10353 if(isPublic($TypePtr, $MemPos)) {
10354 return ($MemPos+1);
10355 }
10356 }
10357 }
10358 return 0;
10359}
10360
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010361sub isReserved($)
10362{ # reserved fields == private
10363 my $MName = $_[0];
10364 if($MName=~/reserved|padding|f_spare/i) {
10365 return 1;
10366 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010367 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010368 return 1;
10369 }
10370 if($MName=~/(pad\d+)/i) {
10371 return 1;
10372 }
10373 return 0;
10374}
10375
10376sub isPublic($$)
10377{
10378 my ($TypePtr, $FieldPos) = @_;
10379 return 0 if(not $TypePtr);
10380 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10381 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10382 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10383 { # by name in C language
10384 # FIXME: add other methods to detect private members
10385 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10386 if($MName=~/priv|abidata|parent_object/i)
10387 { # C-styled private data
10388 return 0;
10389 }
10390 if(lc($MName) eq "abi")
10391 { # ABI information/reserved field
10392 return 0;
10393 }
10394 if(isReserved($MName))
10395 { # reserved fields
10396 return 0;
10397 }
10398 return 1;
10399 }
10400 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10401 { # by access in C++ language
10402 return 1;
10403 }
10404 return 0;
10405}
10406
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010407sub getVTable_Real($$)
10408{
10409 my ($ClassName, $LibVersion) = @_;
10410 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10411 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010412 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010413 if(defined $Type{"VTable"}) {
10414 return %{$Type{"VTable"}};
10415 }
10416 }
10417 return ();
10418}
10419
10420sub cmpVTables($)
10421{
10422 my $ClassName = $_[0];
10423 my $Res = cmpVTables_Real($ClassName, 1);
10424 if($Res==-1) {
10425 $Res = cmpVTables_Model($ClassName);
10426 }
10427 return $Res;
10428}
10429
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010430sub cmpVTables_Model($)
10431{
10432 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010433 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010434 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010435 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010436 return 1;
10437 }
10438 }
10439 return 0;
10440}
10441
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010442sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010443{
10444 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010445 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10446 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010447 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010448 my %VTable_Old = getVTable_Real($ClassName, 1);
10449 my %VTable_New = getVTable_Real($ClassName, 2);
10450 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010451 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010452 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010453 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010454 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010455 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10456 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010457 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010458 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010459 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010460 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010461 my $Entry1 = $VTable_Old{$Offset};
10462 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010463 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010464 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010465 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010466 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010467
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010468 $Entry1 = simpleVEntry($Entry1);
10469 $Entry2 = simpleVEntry($Entry2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030010470
10471 if($Entry1=~/ 0x/ and $Entry2=~/ 0x/)
10472 { # NOTE: problem with vtable-dumper
10473 next;
10474 }
10475
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010476 if($Entry1 ne $Entry2)
10477 { # register as changed
10478 if($Entry1=~/::([^:]+)\Z/)
10479 {
10480 my $M1 = $1;
10481 if($Entry2=~/::([^:]+)\Z/)
10482 {
10483 my $M2 = $1;
10484 if($M1 eq $M2)
10485 { # overridden
10486 next;
10487 }
10488 }
10489 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010490 if(differentDumps("G"))
10491 {
10492 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10493 {
10494 # GCC 4.6.1: -0x00000000000000010
10495 # GCC 4.7.0: -16
10496 next;
10497 }
10498 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010499 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010500 }
10501 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010502 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010503}
10504
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010505sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010506{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010507 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010508 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10509 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010510 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010511 { # already registered
10512 next;
10513 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010514 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010515 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010516 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010517 foreach my $Symbol (@Affected)
10518 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010519 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010520 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010521 "Target"=>$ClassName);
10522 }
10523 }
10524 }
10525}
10526
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010527sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010528{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010529 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010530 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010531 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010532 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010533 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010534 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010535 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010536 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010537 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010538 if($TName_Tid{1}{$ClassName}
10539 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010540 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010541 if(defined $CompleteSignature{1}{$Symbol}
10542 and $CompleteSignature{1}{$Symbol}{"Virt"})
10543 { # override some method in v.1
10544 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010545 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010546 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010547 }
10548 }
10549 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010550 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010551 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010552 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010553 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010554 if($TName_Tid{2}{$ClassName}
10555 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010556 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010557 if(defined $CompleteSignature{2}{$Symbol}
10558 and $CompleteSignature{2}{$Symbol}{"Virt"})
10559 { # override some method in v.2
10560 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010561 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010562 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010563 }
10564 }
10565 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010566 if($Level eq "Binary")
10567 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010568 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010569 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10570 { # check replacements, including pure virtual methods
10571 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10572 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010573 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010574 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10575 if($AddedPos==$RemovedPos)
10576 {
10577 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10578 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10579 last; # other methods will be reported as "added" or "removed"
10580 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010581 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010582 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10583 {
10584 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10585 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010586 next;
10587 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010588 my $ProblemType = "Virtual_Replacement";
10589 my @Affected = ($RemovedVFunc);
10590 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10591 { # pure methods
10592 if(not isUsedClass($ClassId, 1, $Level))
10593 { # not a parameter of some exported method
10594 next;
10595 }
10596 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010597
10598 # affected all methods (both virtual and non-virtual ones)
10599 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10600 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010601 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010602 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010603 foreach my $AffectedInt (@Affected)
10604 {
10605 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10606 { # affected exported methods only
10607 next;
10608 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010609 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10610 next;
10611 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010612 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10613 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010614 "Target"=>get_Signature($AddedVFunc, 2),
10615 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10616 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010617 }
10618 }
10619 }
10620 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010621 if(not checkDump(1, "2.0")
10622 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010623 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010624 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010625 return;
10626 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010627 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010628 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010629 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010630 next if(not $ClassId_Old);
10631 if(not isCreatable($ClassId_Old, 1))
10632 { # skip classes without public constructors (including auto-generated)
10633 # example: class has only a private exported or private inline constructor
10634 next;
10635 }
10636 if($ClassName=~/>/)
10637 { # skip affected template instances
10638 next;
10639 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010640 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010641 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010642 if(not $ClassId_New) {
10643 next;
10644 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010645 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010646 if($Class_New{"Type"}!~/Class|Struct/)
10647 { # became typedef
10648 if($Level eq "Binary") {
10649 next;
10650 }
10651 if($Level eq "Source")
10652 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010653 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010654 if($Class_New{"Type"}!~/Class|Struct/) {
10655 next;
10656 }
10657 $ClassId_New = $Class_New{"Tid"};
10658 }
10659 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030010660
10661 if(not $Class_New{"Size"} or not $Class_Old{"Size"})
10662 { # incomplete info in the ABI dump
10663 next;
10664 }
10665
10666
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010667 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10668 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 +040010669
10670 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10671 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10672
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010673 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010674 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10675 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010676 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10677 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010678 my $Shift_Old = getShift($ClassId_Old, 1);
10679 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010680 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010681 my ($Added, $Removed) = (0, 0);
10682 my @StableBases_Old = ();
10683 foreach my $BaseId (@Bases_Old)
10684 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010685 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010686 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010687 push(@StableBases_Old, $BaseId);
10688 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010689 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010690 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010691 { # removed base
10692 # excluding namespace::SomeClass to SomeClass renaming
10693 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010694 if($Level eq "Binary")
10695 { # Binary-level
10696 if($Shift_Old ne $Shift_New)
10697 { # affected fields
10698 if(havePubFields(\%Class_Old)) {
10699 $ProblemKind .= "_And_Shift";
10700 }
10701 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10702 $ProblemKind .= "_And_Size";
10703 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010704 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010705 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10706 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010707 { # affected v-table
10708 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010709 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010710 }
10711 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010712 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010713 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10714 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010715 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10716 {
10717 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10718 if($ProblemKind=~/VTable/) {
10719 $VTableChanged_M{$SubName}=1;
10720 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010721 }
10722 }
10723 foreach my $Interface (@Affected)
10724 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010725 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10726 next;
10727 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010728 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010729 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010730 "Target"=>$BaseName,
10731 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10732 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10733 "Shift"=>abs($Shift_New-$Shift_Old) );
10734 }
10735 $Removed+=1;
10736 }
10737 }
10738 my @StableBases_New = ();
10739 foreach my $BaseId (@Bases_New)
10740 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010741 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010742 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010743 push(@StableBases_New, $BaseId);
10744 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010745 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010746 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010747 { # added base
10748 # excluding namespace::SomeClass to SomeClass renaming
10749 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010750 if($Level eq "Binary")
10751 { # Binary-level
10752 if($Shift_Old ne $Shift_New)
10753 { # affected fields
10754 if(havePubFields(\%Class_Old)) {
10755 $ProblemKind .= "_And_Shift";
10756 }
10757 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10758 $ProblemKind .= "_And_Size";
10759 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010760 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010761 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10762 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010763 { # affected v-table
10764 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010765 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010766 }
10767 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010768 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010769 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10770 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010771 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10772 {
10773 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10774 if($ProblemKind=~/VTable/) {
10775 $VTableChanged_M{$SubName}=1;
10776 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010777 }
10778 }
10779 foreach my $Interface (@Affected)
10780 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010781 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10782 next;
10783 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010784 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010785 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010786 "Target"=>$BaseName,
10787 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10788 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10789 "Shift"=>abs($Shift_New-$Shift_Old) );
10790 }
10791 $Added+=1;
10792 }
10793 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010794 if($Level eq "Binary")
10795 { # Binary-level
10796 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010797 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10798 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010799 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010800 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010801 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010802 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010803 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010804 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10805 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010806 if($NewPos!=$OldPos)
10807 { # changed position of the base class
10808 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010809 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010810 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10811 next;
10812 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010813 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10814 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010815 "Target"=>$BaseName,
10816 "Old_Value"=>$OldPos-1,
10817 "New_Value"=>$NewPos-1 );
10818 }
10819 }
10820 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10821 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10822 { # became non-virtual base
10823 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10824 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010825 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10826 next;
10827 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010828 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10829 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010830 "Target"=>$BaseName );
10831 }
10832 }
10833 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10834 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10835 { # became virtual base
10836 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10837 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010838 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10839 next;
10840 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010841 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10842 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010843 "Target"=>$BaseName );
10844 }
10845 }
10846 }
10847 }
10848 # detect size changes in base classes
10849 if($Shift_Old!=$Shift_New)
10850 { # size of allocable class
10851 foreach my $BaseId (@StableBases_Old)
10852 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010853 my %BaseType = get_Type($BaseId, 1);
10854 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010855 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010856 if($Size_Old ne $Size_New
10857 and $Size_Old and $Size_New)
10858 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010859 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010860 if(isCopyingClass($BaseId, 1)) {
10861 $ProblemType = "Size_Of_Copying_Class";
10862 }
10863 elsif($AllocableClass{1}{$BaseType{"Name"}})
10864 {
10865 if($Size_New>$Size_Old)
10866 { # increased size
10867 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010868 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010869 else
10870 { # decreased size
10871 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10872 if(not havePubFields(\%Class_Old))
10873 { # affected class has no public members
10874 next;
10875 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010876 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010877 }
10878 next if(not $ProblemType);
10879 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10880 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010881 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10882 next;
10883 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010884 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10885 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010886 "Target"=>$BaseType{"Name"},
10887 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10888 "New_Size"=>$Size_New*$BYTE_SIZE );
10889 }
10890 }
10891 }
10892 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010893 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010894 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010895 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010896 { # compare virtual tables size in base classes
10897 my $VShift_Old = getVShift($ClassId_Old, 1);
10898 my $VShift_New = getVShift($ClassId_New, 2);
10899 if($VShift_Old ne $VShift_New)
10900 { # changes in the base class or changes in the list of base classes
10901 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10902 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10903 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010904 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010905 foreach my $BaseId (@AllBases_Old)
10906 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010907 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010908 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010909 { # lost base
10910 next;
10911 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010912 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10913 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010914 if($VSize_Old!=$VSize_New)
10915 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010916 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010917 { # TODO: affected non-virtual methods?
10918 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010919 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10920 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010921 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010922 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010923 { # skip interfaces that have not changed the absolute virtual position
10924 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010925 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010926 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10927 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010928 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010929 $VTableChanged_M{$BaseType{"Name"}} = 1;
10930 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010931 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10932 { # the reason of the layout change: added virtual functions
10933 next if($VirtualReplacement{$VirtFunc});
10934 my $ProblemType = "Added_Virtual_Method";
10935 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10936 $ProblemType = "Added_Pure_Virtual_Method";
10937 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010938 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010939 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010940 "Target"=>get_Signature($VirtFunc, 2) );
10941 }
10942 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
10943 { # the reason of the layout change: removed virtual functions
10944 next if($VirtualReplacement{$VirtFunc});
10945 my $ProblemType = "Removed_Virtual_Method";
10946 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
10947 $ProblemType = "Removed_Pure_Virtual_Method";
10948 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010949 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010950 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010951 "Target"=>get_Signature($VirtFunc, 1) );
10952 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010953 }
10954 }
10955 }
10956 }
10957 }
10958 }
10959 }
10960}
10961
10962sub isCreatable($$)
10963{
10964 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010965 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010966 or isCopyingClass($ClassId, $LibVersion)) {
10967 return 1;
10968 }
10969 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10970 { # Fix for incomplete data: if this class has
10971 # a base class then it should also has a constructor
10972 return 1;
10973 }
10974 if($ReturnedClass{$LibVersion}{$ClassId})
10975 { # returned by some method of this class
10976 # or any other class
10977 return 1;
10978 }
10979 return 0;
10980}
10981
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010982sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010983{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010984 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010985 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
10986 { # parameter of some exported method
10987 return 1;
10988 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010989 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
10990 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010991 { # method from target class
10992 return 1;
10993 }
10994 return 0;
10995}
10996
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010997sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010998{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010999 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011000 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011001 # - virtual
11002 # - pure-virtual
11003 # - non-virtual
11004 if($CompleteSignature{1}{$Interface}{"Data"})
11005 { # global data is not affected
11006 return;
11007 }
11008 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011009 if(not $Class_Id) {
11010 return;
11011 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011012 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011013 if(cmpVTables_Real($CName, 1)==0)
11014 { # no changes
11015 return;
11016 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011017 $CheckedTypes{$Level}{$CName} = 1;
11018 if($Level eq "Binary")
11019 { # Binary-level
11020 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11021 and not isUsedClass($Class_Id, 1, $Level))
11022 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011023 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011024 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011025 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011026 }
11027 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11028 {
11029 if(defined $VirtualTable{2}{$CName}{$Func}
11030 and defined $CompleteSignature{2}{$Func})
11031 {
11032 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11033 and $CompleteSignature{2}{$Func}{"PureVirt"})
11034 { # became pure virtual
11035 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11036 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011037 "Target"=>get_Signature_M($Func, 1) );
11038 $VTableChanged_M{$CName} = 1;
11039 }
11040 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11041 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11042 { # became non-pure virtual
11043 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11044 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011045 "Target"=>get_Signature_M($Func, 1) );
11046 $VTableChanged_M{$CName} = 1;
11047 }
11048 }
11049 }
11050 if($Level eq "Binary")
11051 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011052 # check virtual table structure
11053 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11054 {
11055 next if($Interface eq $AddedVFunc);
11056 next if($VirtualReplacement{$AddedVFunc});
11057 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11058 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11059 { # pure virtual methods affect all others (virtual and non-virtual)
11060 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011061 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011062 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011063 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011064 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011065 elsif(not defined $VirtualTable{1}{$CName}
11066 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011067 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011068 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011069 { # became polymorphous class, added v-table pointer
11070 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011071 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011072 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011073 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011074 }
11075 else
11076 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011077 my $VSize_Old = getVTable_Size($CName, 1);
11078 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011079 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011080 if(isCopyingClass($Class_Id, 1))
11081 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11082 my $ProblemType = "Added_Virtual_Method";
11083 if(isLeafClass($Class_Id, 1)) {
11084 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11085 }
11086 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11087 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011088 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011089 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011090 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011091 else
11092 {
11093 my $ProblemType = "Added_Virtual_Method";
11094 if(isLeafClass($Class_Id, 1)) {
11095 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11096 }
11097 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11098 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011099 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011100 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011101 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011102 }
11103 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011104 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11105 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011106 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011107 if(defined $VirtualTable{1}{$CName}
11108 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011109 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011110 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11111 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011112
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011113 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011114 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011115 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11116 foreach my $ASymbol (@Affected)
11117 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011118 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11119 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011120 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011121 next;
11122 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011123 }
11124 $CheckedSymbols{$Level}{$ASymbol} = 1;
11125 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11126 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011127 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011128 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011129 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011130 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011131 }
11132 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011133 else {
11134 # safe
11135 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011136 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011137 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11138 {
11139 next if($VirtualReplacement{$RemovedVFunc});
11140 if($RemovedVFunc eq $Interface
11141 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11142 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011143 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011144 next;
11145 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011146 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011147 { # became non-polymorphous class, removed v-table pointer
11148 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11149 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011150 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011151 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011152 }
11153 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11154 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11155 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011156 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011157 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011158 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11159 next;
11160 }
11161 my $VPos_New = -1;
11162 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011163 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011164 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11165 }
11166 else
11167 {
11168 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011169 next;
11170 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011171 }
11172 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11173 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11174 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11175 {
11176 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11177 foreach my $ASymbol (@Affected)
11178 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011179 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11180 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011181 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011182 next;
11183 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011184 }
11185 my $ProblemType = "Removed_Virtual_Method";
11186 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11187 $ProblemType = "Removed_Pure_Virtual_Method";
11188 }
11189 $CheckedSymbols{$Level}{$ASymbol} = 1;
11190 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11191 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011192 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011193 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011194 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011195 }
11196 }
11197 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011198 }
11199 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011200 else
11201 { # Source-level
11202 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011203 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011204 next if($Interface eq $AddedVFunc);
11205 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011206 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011207 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11208 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011209 "Target"=>get_Signature($AddedVFunc, 2) );
11210 }
11211 }
11212 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11213 {
11214 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11215 {
11216 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11217 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011218 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011219 }
11220 }
11221 }
11222}
11223
11224sub find_MemberPair_Pos_byName($$)
11225{
11226 my ($Member_Name, $Pair_Type) = @_;
11227 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11228 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11229 {
11230 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11231 {
11232 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11233 $Name=~s/\A[_]+|[_]+\Z//g;
11234 if($Name eq $Member_Name) {
11235 return $MemberPair_Pos;
11236 }
11237 }
11238 }
11239 return "lost";
11240}
11241
11242sub find_MemberPair_Pos_byVal($$)
11243{
11244 my ($Member_Value, $Pair_Type) = @_;
11245 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11246 {
11247 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11248 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11249 return $MemberPair_Pos;
11250 }
11251 }
11252 return "lost";
11253}
11254
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011255sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011256{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011257 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011258 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011259 if( $_->{"T1"} eq $_[0]
11260 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011261 {
11262 return 1;
11263 }
11264 }
11265 return 0;
11266}
11267
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011268sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011269{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011270 my %IDs = (
11271 "T1" => $_[0],
11272 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011273 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011274 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011275}
11276
11277sub isRenamed($$$$$)
11278{
11279 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11280 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11281 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011282 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011283 if(not defined $Type2->{"Memb"}{$MemPos}) {
11284 return "";
11285 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011286 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011287 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011288
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011289 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11290 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011291 if($MemberPair_Pos_Rev eq "lost")
11292 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011293 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11294 { # base type match
11295 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011296 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011297 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11298 { # exact type match
11299 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011300 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011301 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11302 { # size match
11303 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011304 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011305 if(isReserved($Pair_Name))
11306 { # reserved fields
11307 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011308 }
11309 }
11310 return "";
11311}
11312
11313sub isLastElem($$)
11314{
11315 my ($Pos, $TypeRef) = @_;
11316 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11317 if($Name=~/last|count|max|total/i)
11318 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11319 return 1;
11320 }
11321 elsif($Name=~/END|NLIMITS\Z/)
11322 { # __RLIMIT_NLIMITS
11323 return 1;
11324 }
11325 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11326 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11327 { # NImageFormats, NColorRoles
11328 return 1;
11329 }
11330 return 0;
11331}
11332
11333sub nonComparable($$)
11334{
11335 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011336
11337 my $N1 = $T1->{"Name"};
11338 my $N2 = $T2->{"Name"};
11339
11340 $N1=~s/\A(struct|union|enum) //;
11341 $N2=~s/\A(struct|union|enum) //;
11342
11343 if($N1 ne $N2
11344 and not isAnon($N1)
11345 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011346 { # different names
11347 if($T1->{"Type"} ne "Pointer"
11348 or $T2->{"Type"} ne "Pointer")
11349 { # compare base types
11350 return 1;
11351 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011352 if($N1!~/\Avoid\s*\*/
11353 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011354 {
11355 return 1;
11356 }
11357 }
11358 elsif($T1->{"Type"} ne $T2->{"Type"})
11359 { # different types
11360 if($T1->{"Type"} eq "Class"
11361 and $T2->{"Type"} eq "Struct")
11362 { # "class" to "struct"
11363 return 0;
11364 }
11365 elsif($T2->{"Type"} eq "Class"
11366 and $T1->{"Type"} eq "Struct")
11367 { # "struct" to "class"
11368 return 0;
11369 }
11370 else
11371 { # "class" to "enum"
11372 # "union" to "class"
11373 # ...
11374 return 1;
11375 }
11376 }
11377 return 0;
11378}
11379
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011380sub isOpaque($)
11381{
11382 my $T = $_[0];
11383 if(not defined $T->{"Memb"})
11384 {
11385 return 1;
11386 }
11387 return 0;
11388}
11389
11390sub removeVPtr($)
11391{ # support for old ABI dumps
11392 my $TPtr = $_[0];
11393 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11394 if($#Pos>=1)
11395 {
11396 foreach my $Pos (0 .. $#Pos-1)
11397 {
11398 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11399 }
11400 delete($TPtr->{"Memb"}{$#Pos});
11401 }
11402}
11403
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011404sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011405{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011406 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011407 return {} if(not $Type1_Id or not $Type2_Id);
11408
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011409 if(defined $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011410 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011411 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011412 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011413
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011414 my %Type1 = get_Type($Type1_Id, 1);
11415 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011416 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011417 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011418 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011419
11420 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011421 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11422 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011423
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011424 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11425
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011426 if(defined $UsedDump{1}{"DWARF"})
11427 {
11428 if($Type1_Pure{"Name"} eq "__unknown__"
11429 or $Type2_Pure{"Name"} eq "__unknown__")
11430 { # Error ABI dump
11431 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11432 }
11433 }
11434
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011435 my %SubProblems = ();
11436
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011437 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11438 {
11439 if($Type1_Pure{"Type"}=~/Struct|Union/
11440 and $Type2_Pure{"Type"}=~/Struct|Union/)
11441 {
11442 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11443 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011444 if(not defined $UsedDump{1}{"DWARF"}
11445 and not defined $UsedDump{2}{"DWARF"})
11446 {
11447 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11448 "Target"=>$Type1_Pure{"Name"},
11449 "Type_Name"=>$Type1_Pure{"Name"} );
11450 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011451
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011452 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011453 }
11454 }
11455 }
11456
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011457 if(not $Type1_Pure{"Size"}
11458 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011459 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011460 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11461 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11462 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011463 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011464 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011465 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011466 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011467 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011468 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011469 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011470 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11471 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11472 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011473
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030011474 if(not isTargetType($Type1_Pure{"Tid"}, 1)) {
11475 return {};
Andrey Ponomarenko28874762015-08-28 21:59:28 +030011476 }
11477
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011478 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11479 { # support for old ABI dumps
11480 # _vptr field added in 3.0
11481 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11482 {
11483 if(defined $Type2_Pure{"Memb"}
11484 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11485 {
11486 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11487 delete($Type2_Pure{"Memb"}{0});
11488 }
11489 else {
11490 removeVPtr(\%Type2_Pure);
11491 }
11492 }
11493 }
11494 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11495 {
11496 if(defined $Type1_Pure{"Memb"}
11497 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11498 {
11499 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11500 delete($Type1_Pure{"Memb"}{0});
11501 }
11502 else {
11503 removeVPtr(\%Type1_Pure);
11504 }
11505 }
11506 }
11507 }
11508
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011509 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11510 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011511
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030011512 if(%Typedef_1 and %Typedef_2
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011513 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11514 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011515 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011516 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11517 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011518 if($Base_1{"Name"} ne $Base_2{"Name"})
11519 {
11520 if(differentDumps("G")
11521 or differentDumps("V"))
11522 { # different GCC versions or different dumps
11523 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11524 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11525 # std::__va_list and __va_list
11526 $Base_1{"Name"}=~s/\A(\w+::)+//;
11527 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011528 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11529 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011530 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011531 }
11532 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11533 and $Base_1{"Name"} ne $Base_2{"Name"})
11534 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011535 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011536 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011537 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011538 {
11539 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11540 "Target"=>$Typedef_1{"Name"},
11541 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011542 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11543 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11544 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011545 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11546 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030011547
11548 if(defined $UsedDump{1}{"DWARF"})
11549 {
11550 if($Base1_Pure{"Name"}=~/\b__unknown__\b/
11551 or $Base2_Pure{"Name"}=~/\b__unknown__\b/)
11552 { # Error ABI dump
11553 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = {});
11554 }
11555 }
11556
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011557 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011558 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011559 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11560 {
11561 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11562 "Target"=>$Typedef_1{"Name"},
11563 "Type_Name"=>$Typedef_1{"Name"},
11564 "Old_Value"=>$Base_1{"Name"},
11565 "New_Value"=>$Base_2{"Name"} );
11566 }
11567 else
11568 {
11569 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11570 "Target"=>$Typedef_1{"Name"},
11571 "Type_Name"=>$Typedef_1{"Name"},
11572 "Old_Value"=>$Base_1{"Name"},
11573 "New_Value"=>$Base_2{"Name"} );
11574 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011575 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011576 }
11577 }
11578 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11579 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011580 my $TT1 = $Type1_Pure{"Type"};
11581 my $TT2 = $Type2_Pure{"Type"};
11582
11583 if($TT1 ne $TT2
11584 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011585 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011586 my $Short1 = $Type1_Pure{"Name"};
11587 my $Short2 = $Type2_Pure{"Name"};
11588
11589 $Short1=~s/\A\Q$TT1\E //ig;
11590 $Short2=~s/\A\Q$TT2\E //ig;
11591
11592 if($Short1 eq $Short2)
11593 {
11594 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11595 "Target"=>$Type1_Pure{"Name"},
11596 "Type_Name"=>$Type1_Pure{"Name"},
11597 "Old_Value"=>lc($Type1_Pure{"Type"}),
11598 "New_Value"=>lc($Type2_Pure{"Type"}) );
11599 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011600 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011601 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011602 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011603 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011604 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11605 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11606 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11607 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011608 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011609 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011610 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011611 {
11612 my $ProblemKind = "DataType_Size";
11613 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011614 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011615 {
11616 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11617 $ProblemKind = "Size_Of_Copying_Class";
11618 }
11619 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11620 {
11621 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11622 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11623 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011624 else
11625 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011626 # descreased size of allocable class
11627 # it has no special effects
11628 }
11629 }
11630 }
11631 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11632 "Target"=>$Type1_Pure{"Name"},
11633 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011634 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011635 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011636 }
11637 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011638 if(defined $Type1_Pure{"BaseType"}
11639 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011640 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011641 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11642 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011643 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011644 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11645 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011646 }
11647 }
11648 }
11649 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11650 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11651 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11652 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11653 { # detect removed and renamed fields
11654 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11655 next if(not $Member_Name);
11656 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);
11657 if($MemberPair_Pos eq "lost")
11658 {
11659 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11660 {
11661 if(isUnnamed($Member_Name))
11662 { # support for old-version dumps
11663 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011664 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011665 next;
11666 }
11667 }
11668 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11669 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011670 $RenamedField{$Member_Pos} = $RenamedTo;
11671 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011672 }
11673 else
11674 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011675 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011676 }
11677 }
11678 elsif($Type1_Pure{"Type"} eq "Enum")
11679 {
11680 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11681 next if($Member_Value1 eq "");
11682 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11683 if($MemberPair_Pos ne "lost")
11684 { # renamed
11685 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11686 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11687 if($MemberPair_Pos_Rev eq "lost")
11688 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011689 $RenamedField{$Member_Pos} = $RenamedTo;
11690 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011691 }
11692 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011693 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011694 }
11695 }
11696 else
11697 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011698 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011699 }
11700 }
11701 }
11702 else
11703 { # related
11704 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11705 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11706 }
11707 }
11708 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11709 { # detect added fields
11710 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11711 next if(not $Member_Name);
11712 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);
11713 if($MemberPair_Pos eq "lost")
11714 {
11715 if(isUnnamed($Member_Name))
11716 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011717 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011718 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011719 next;
11720 }
11721 }
11722 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11723 {
11724 if(not $RenamedField_Rev{$Member_Pos})
11725 { # added
11726 $AddedField{$Member_Pos}=1;
11727 }
11728 }
11729 }
11730 }
11731 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11732 { # detect moved fields
11733 my (%RelPos, %RelPosName, %AbsPos) = ();
11734 my $Pos = 0;
11735 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11736 { # relative positions in 1st version
11737 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11738 next if(not $Member_Name);
11739 if(not $RemovedField{$Member_Pos})
11740 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011741 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011742 $RelPosName{1}{$Pos} = $Member_Name;
11743 $AbsPos{1}{$Pos++} = $Member_Pos;
11744 }
11745 }
11746 $Pos = 0;
11747 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11748 { # relative positions in 2nd version
11749 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11750 next if(not $Member_Name);
11751 if(not $AddedField{$Member_Pos})
11752 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011753 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011754 $RelPosName{2}{$Pos} = $Member_Name;
11755 $AbsPos{2}{$Pos++} = $Member_Pos;
11756 }
11757 }
11758 foreach my $Member_Name (keys(%{$RelPos{1}}))
11759 {
11760 my $RPos1 = $RelPos{1}{$Member_Name};
11761 my $AbsPos1 = $NameToPosA{$Member_Name};
11762 my $Member_Name2 = $Member_Name;
11763 if(my $RenamedTo = $RenamedField{$AbsPos1})
11764 { # renamed
11765 $Member_Name2 = $RenamedTo;
11766 }
11767 my $RPos2 = $RelPos{2}{$Member_Name2};
11768 if($RPos2 ne "" and $RPos1 ne $RPos2)
11769 { # different relative positions
11770 my $AbsPos2 = $NameToPosB{$Member_Name2};
11771 if($AbsPos1 ne $AbsPos2)
11772 { # different absolute positions
11773 my $ProblemType = "Moved_Field";
11774 if(not isPublic(\%Type1_Pure, $AbsPos1))
11775 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011776 if($Level eq "Source") {
11777 next;
11778 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011779 $ProblemType = "Moved_Private_Field";
11780 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011781 if($Level eq "Binary"
11782 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011783 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011784 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011785 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011786 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011787 if($MemSize1 ne $MemSize2) {
11788 $ProblemType .= "_And_Size";
11789 }
11790 }
11791 if($ProblemType eq "Moved_Private_Field") {
11792 next;
11793 }
11794 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11795 "Target"=>$Member_Name,
11796 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011797 "Old_Value"=>$RPos1,
11798 "New_Value"=>$RPos2 );
11799 }
11800 }
11801 }
11802 }
11803 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011804 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011805 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11806 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011807 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011808 if(my $RenamedTo = $RenamedField{$Member_Pos})
11809 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011810 if(defined $Constants{2}{$Member_Name})
11811 {
11812 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11813 { # define OLD NEW
11814 next; # Safe
11815 }
11816 }
11817
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011818 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11819 {
11820 if(isPublic(\%Type1_Pure, $Member_Pos))
11821 {
11822 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11823 "Target"=>$Member_Name,
11824 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011825 "Old_Value"=>$Member_Name,
11826 "New_Value"=>$RenamedTo );
11827 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011828 elsif(isReserved($Member_Name))
11829 {
11830 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11831 "Target"=>$Member_Name,
11832 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011833 "Old_Value"=>$Member_Name,
11834 "New_Value"=>$RenamedTo );
11835 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011836 }
11837 elsif($Type1_Pure{"Type"} eq "Enum")
11838 {
11839 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11840 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11841 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011842 "Old_Value"=>$Member_Name,
11843 "New_Value"=>$RenamedTo );
11844 }
11845 }
11846 elsif($RemovedField{$Member_Pos})
11847 { # removed
11848 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11849 {
11850 my $ProblemType = "Removed_Field";
11851 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011852 or isUnnamed($Member_Name))
11853 {
11854 if($Level eq "Source") {
11855 next;
11856 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011857 $ProblemType = "Removed_Private_Field";
11858 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011859 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011860 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011861 {
11862 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11863 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011864 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 +040011865 { # changed offset
11866 $ProblemType .= "_And_Layout";
11867 }
11868 }
11869 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11870 { # affected size
11871 $ProblemType .= "_And_Size";
11872 }
11873 }
11874 if($ProblemType eq "Removed_Private_Field") {
11875 next;
11876 }
11877 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11878 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011879 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011880 }
11881 elsif($Type2_Pure{"Type"} eq "Union")
11882 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011883 if($Level eq "Binary"
11884 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011885 {
11886 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11887 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011888 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011889 }
11890 else
11891 {
11892 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11893 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011894 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011895 }
11896 }
11897 elsif($Type1_Pure{"Type"} eq "Enum")
11898 {
11899 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11900 "Target"=>$Member_Name,
11901 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011902 "Old_Value"=>$Member_Name );
11903 }
11904 }
11905 else
11906 { # changed
11907 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11908 if($Type1_Pure{"Type"} eq "Enum")
11909 {
11910 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11911 next if($Member_Value1 eq "");
11912 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11913 next if($Member_Value2 eq "");
11914 if($Member_Value1 ne $Member_Value2)
11915 {
11916 my $ProblemType = "Enum_Member_Value";
11917 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11918 $ProblemType = "Enum_Last_Member_Value";
11919 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011920 if($SkipConstants{1}{$Member_Name}) {
11921 $ProblemType = "Enum_Private_Member_Value";
11922 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011923 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11924 "Target"=>$Member_Name,
11925 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011926 "Old_Value"=>$Member_Value1,
11927 "New_Value"=>$Member_Value2 );
11928 }
11929 }
11930 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11931 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011932 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
11933 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
11934
11935 if($Access1 ne "private"
11936 and $Access2 eq "private")
11937 {
11938 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
11939 "Target"=>$Member_Name,
11940 "Type_Name"=>$Type1_Pure{"Name"});
11941 }
11942 elsif($Access1 ne "protected"
11943 and $Access1 ne "private"
11944 and $Access2 eq "protected")
11945 {
11946 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
11947 "Target"=>$Member_Name,
11948 "Type_Name"=>$Type1_Pure{"Name"});
11949 }
11950
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011951 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
11952 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011953 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011954 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
11955 $SizeV1 = $BSize1;
11956 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011957 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011958 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
11959 $SizeV2 = $BSize2;
11960 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011961 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
11962 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011963 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011964 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011965 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011966 {
11967 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
11968 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
11969 { # field size change (including anon-structures and unions)
11970 # - same types
11971 # - unnamed types
11972 # - bitfields
11973 my $ProblemType = "Field_Size";
11974 if(not isPublic(\%Type1_Pure, $Member_Pos)
11975 or isUnnamed($Member_Name))
11976 { # should not be accessed by applications, goes to "Low Severity"
11977 # example: "abidata" members in GStreamer types
11978 $ProblemType = "Private_".$ProblemType;
11979 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011980 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 +040011981 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011982 if($Type2_Pure{"Type"} ne "Union"
11983 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011984 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011985 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 +040011986 { # changed offset
11987 $ProblemType .= "_And_Layout";
11988 }
11989 }
11990 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11991 $ProblemType .= "_And_Type_Size";
11992 }
11993 }
11994 if($ProblemType eq "Private_Field_Size")
11995 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011996 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040011997 if($ProblemType eq "Field_Size")
11998 {
11999 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12000 { # Low severity
12001 $ProblemType = "Struct_Field_Size_Increased";
12002 }
12003 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012004 if($ProblemType)
12005 { # register a problem
12006 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12007 "Target"=>$Member_Name,
12008 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012009 "Old_Size"=>$SizeV1,
12010 "New_Size"=>$SizeV2);
12011 }
12012 }
12013 }
12014 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12015 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12016 { # do NOT check bitfield type changes
12017 next;
12018 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012019 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012020 {
12021 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12022 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12023 {
12024 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12025 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012026 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012027 }
12028 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12029 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12030 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012031 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012032 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012033 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012034 }
12035 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012036 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12037 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012038 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012039 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12040 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012041
12042 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012043 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012044 or $ProblemType eq "Field_Type_And_Size"
12045 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012046 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012047 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012048 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012049 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012050 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012051 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012052 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012053 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012054 }
12055 }
12056 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12057 {
12058 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012059 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012060 }
12061 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012062 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012063 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012064 }
12065 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12066 {
12067 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012068 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012069 }
12070 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012071 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012072 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012073 }
12074 }
12075 }
12076
12077 if($Level eq "Source")
12078 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012079 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012080 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012081 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12082 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012083
12084 if($ProblemType eq "Field_Type")
12085 {
12086 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012087 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012088 }
12089 }
12090 }
12091 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012092
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012093 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012094 {
12095 my $ProblemType_Init = $ProblemType;
12096 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012097 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012098 if(not isPublic(\%Type1_Pure, $Member_Pos)
12099 or isUnnamed($Member_Name)) {
12100 $ProblemType = "Private_".$ProblemType;
12101 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012102 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 +040012103 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012104 if($Type2_Pure{"Type"} ne "Union"
12105 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012106 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012107 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 +040012108 { # changed offset
12109 $ProblemType .= "_And_Layout";
12110 }
12111 }
12112 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12113 $ProblemType .= "_And_Type_Size";
12114 }
12115 }
12116 }
12117 else
12118 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012119 # TODO: Private_Field_Type rule?
12120
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012121 if(not isPublic(\%Type1_Pure, $Member_Pos)
12122 or isUnnamed($Member_Name)) {
12123 next;
12124 }
12125 }
12126 if($ProblemType eq "Private_Field_Type_And_Size")
12127 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012128 }
12129 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12130 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012131 "Type_Name"=>$Type1_Pure{"Name"});
12132
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012133 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012134 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012135 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012136 }
12137 }
12138 if(not isPublic(\%Type1_Pure, $Member_Pos))
12139 { # do NOT check internal type changes
12140 next;
12141 }
12142 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012143 { # checking member type changes
12144 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12145
12146 my %DupProblems = ();
12147
12148 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012149 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012150 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012151 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012152 if(not defined $AllAffected)
12153 {
12154 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12155 next;
12156 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012157 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012158
12159 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12160 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12161
12162 if(not defined $AllAffected)
12163 {
12164 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012165 }
12166 }
12167 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012168
12169 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012170 }
12171 }
12172 }
12173 }
12174 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12175 { # checking added members, public and private
12176 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12177 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012178 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012179 if($AddedField{$Member_Pos})
12180 { # added
12181 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12182 {
12183 my $ProblemType = "Added_Field";
12184 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012185 or isUnnamed($Member_Name))
12186 {
12187 if($Level eq "Source") {
12188 next;
12189 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012190 $ProblemType = "Added_Private_Field";
12191 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012192 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012193 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012194 {
12195 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12196 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012197 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 +040012198 { # changed offset
12199 $ProblemType .= "_And_Layout";
12200 }
12201 }
12202 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12203 $ProblemType .= "_And_Size";
12204 }
12205 }
12206 if($ProblemType eq "Added_Private_Field")
12207 { # skip added private fields
12208 next;
12209 }
12210 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12211 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012212 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012213 }
12214 elsif($Type2_Pure{"Type"} eq "Union")
12215 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012216 if($Level eq "Binary"
12217 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012218 {
12219 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12220 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012221 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012222 }
12223 else
12224 {
12225 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12226 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012227 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012228 }
12229 }
12230 elsif($Type2_Pure{"Type"} eq "Enum")
12231 {
12232 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12233 next if($Member_Value eq "");
12234 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12235 "Target"=>$Member_Name,
12236 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012237 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012238 }
12239 }
12240 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012241
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012242 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012243 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012244}
12245
12246sub isUnnamed($) {
12247 return $_[0]=~/\Aunnamed\d+\Z/;
12248}
12249
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012250sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012251{
12252 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012253 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12254 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12255 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12256 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012257 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012258 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012259 }
12260 return $TypeName;
12261}
12262
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012263sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012264{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012265 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012266 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012267 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12268 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012269 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012270 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12271 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012272 return () if(not $Type{"Type"});
12273 if($Type{"Type"} ne $Type_Type)
12274 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012275 return () if(not $Type{"BaseType"});
12276 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012277 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012278 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012279 return %Type;
12280}
12281
12282my %TypeSpecAttributes = (
12283 "Const" => 1,
12284 "Volatile" => 1,
12285 "ConstVolatile" => 1,
12286 "Restrict" => 1,
12287 "Typedef" => 1
12288);
12289
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012290sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012291{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012292 my ($TypeId, $Info) = @_;
12293 if(not $TypeId or not $Info
12294 or not $Info->{$TypeId}) {
12295 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012296 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012297 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12298 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12299 }
12300 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012301 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012302 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012303 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012304 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012305 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012306 return %Type;
12307}
12308
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012309sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012310{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012311 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012312 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012313 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12314 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012315 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012316 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12317 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012318 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12319 my $PLevel = 0;
12320 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12321 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012322 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012323 return $PLevel if(not $Type{"BaseType"});
12324 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12325 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12326 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012327}
12328
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012329sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012330{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012331 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012332 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012333 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12334 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012335 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012336 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12337 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012338 return %Type if(not $Type{"BaseType"});
12339 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012340 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012341 return %Type;
12342}
12343
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012344sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012345{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012346 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012347 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012348 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12349 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012350 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012351 my $Qual = "";
12352 if($Type{"Type"} eq "Pointer") {
12353 $Qual .= "*";
12354 }
12355 elsif($Type{"Type"} eq "Ref") {
12356 $Qual .= "&";
12357 }
12358 elsif($Type{"Type"} eq "ConstVolatile") {
12359 $Qual .= "const volatile";
12360 }
12361 elsif($Type{"Type"} eq "Const"
12362 or $Type{"Type"} eq "Volatile"
12363 or $Type{"Type"} eq "Restrict") {
12364 $Qual .= lc($Type{"Type"});
12365 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012366 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012367 return $BQual.$Qual;
12368}
12369
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012370sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012371{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012372 my ($TypeId, $Info) = @_;
12373 if(not $TypeId or not $Info
12374 or not $Info->{$TypeId}) {
12375 return ();
12376 }
12377 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012378 return %Type if(not $Type{"BaseType"});
12379 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012380 {
12381 if($Info->{$BTid}) {
12382 return %{$Info->{$BTid}};
12383 }
12384 else { # something is going wrong
12385 return ();
12386 }
12387 }
12388 else {
12389 return %Type;
12390 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012391}
12392
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012393sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012394{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012395 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012396 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012397 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12398 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012399}
12400
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012401sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012402{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012403 my $Symbol = $_[0];
12404 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12405}
12406
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012407sub isInLineInst($$) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012408 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12409}
12410
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012411sub isTemplateInstance($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012412{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012413 my ($SInfo, $LibVersion) = @_;
12414
12415 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012416 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012417 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012418 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012419 if(index($ClassName,"<")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012420 return 1;
12421 }
12422 }
12423 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012424 if(my $ShortName = $SInfo->{"ShortName"})
12425 {
12426 if(index($ShortName,"<")!=-1
12427 and index($ShortName,">")!=-1) {
12428 return 1;
12429 }
12430 }
12431
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012432 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012433}
12434
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012435sub isTemplateSpec($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012436{
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012437 my ($SInfo, $LibVersion) = @_;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012438 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012439 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012440 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012441 { # class specialization
12442 return 1;
12443 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012444 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012445 { # method specialization
12446 return 1;
12447 }
12448 }
12449 return 0;
12450}
12451
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012452sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012453{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012454 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012455
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012456 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012457 { # non-public global data
12458 return 0;
12459 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012460
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012461 if(defined $SkipInternalSymbols)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012462 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012463 return 0 if($Symbol=~/($SkipInternalSymbols)/);
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012464 }
12465
Andrey Ponomarenko28874762015-08-28 21:59:28 +030012466 if($Symbol=~/\A_Z/)
12467 {
12468 if($Symbol=~/[CD][3-4]E/) {
12469 return 0;
12470 }
12471 }
12472
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012473 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012474 { # support for old ABI dumps in --headers-only mode
12475 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12476 {
12477 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12478 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012479 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012480 if(not $PType or $PType eq "Unknown") {
12481 return 0;
12482 }
12483 }
12484 }
12485 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012486 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012487 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012488 my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"};
12489
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012490 if($SkipSymbols{$LibVersion}{$Symbol})
12491 { # user defined symbols to ignore
12492 return 0;
12493 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012494
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012495 if($SymbolsListPath and not $SymbolsList{$Symbol})
12496 { # user defined symbols
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012497 if(not $TargetHeadersPath or not $Header
12498 or not is_target_header($Header, 1))
12499 { # -symbols-list | -headers-list
12500 return 0;
12501 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012502 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012503
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012504 if($AppPath and not $SymbolsList_App{$Symbol})
12505 { # user defined symbols (in application)
12506 return 0;
12507 }
12508
12509 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
12510
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030012511 if($ClassId)
12512 {
12513 if(not isTargetType($ClassId, $LibVersion)) {
12514 return 0;
12515 }
12516 }
12517
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012518 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12519 if(not $NameSpace and $ClassId)
12520 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012521 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012522 }
12523 if($NameSpace)
12524 { # user defined namespaces to ignore
12525 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12526 return 0;
12527 }
12528 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12529 { # nested namespaces
12530 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12531 return 0;
12532 }
12533 }
12534 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012535 if($Header)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012536 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012537 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012538 { # --skip-headers or <skip_headers> (not <skip_including>)
12539 if($Skip==1) {
12540 return 0;
12541 }
12542 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012543 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012544 if($TypesListPath and $ClassId)
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012545 { # user defined types
12546 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
12547
12548 if(not $TypesList{$CName})
12549 {
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012550 if(my $NS = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"})
12551 {
12552 $CName=~s/\A\Q$NS\E\:\://g;
12553 }
12554
12555 if(not $TypesList{$CName})
12556 {
12557 my $Found = 0;
12558
12559 while($CName=~s/\:\:.+?\Z//)
12560 {
12561 if($TypesList{$CName})
12562 {
12563 $Found = 1;
12564 last;
12565 }
12566 }
12567
12568 if(not $Found) {
12569 return 0;
12570 }
12571 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030012572 }
12573 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030012574
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012575 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12576 { # non-target symbols
12577 return 0;
12578 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012579 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012580 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012581 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
12582 or isInLineInst($CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012583 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012584 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12585 { # inline virtual methods
12586 if($Type=~/InlineVirt/) {
12587 return 1;
12588 }
12589 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12590 if(not $Allocable)
12591 { # check bases
12592 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12593 {
12594 if(not isCopyingClass($DCId, $LibVersion))
12595 { # exists a derived class without default c-tor
12596 $Allocable=1;
12597 last;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012598 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012599 }
12600 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012601 if(not $Allocable) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012602 return 0;
12603 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012604 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012605 else
12606 { # inline non-virtual methods
12607 return 0;
12608 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012609 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012610 }
12611 }
12612 return 1;
12613}
12614
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012615sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012616{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012617 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012618 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12619 {
12620 if(link_symbol($Symbol, 1, "+Deps"))
12621 { # linker can find a new symbol
12622 # in the old-version library
12623 # So, it's not a new symbol
12624 next;
12625 }
12626 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012627 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012628 next;
12629 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012630 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012631 }
12632}
12633
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012634sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012635{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012636 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012637 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12638 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012639 if(link_symbol($Symbol, 2, "+Deps"))
12640 { # linker can find an old symbol
12641 # in the new-version library
12642 next;
12643 }
12644 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012645 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012646 next;
12647 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012648 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012649 }
12650}
12651
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012652sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012653{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012654 my $Level = $_[0];
12655 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012656 { # checking added symbols
12657 next if($CompleteSignature{2}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012658 next if(not $CompleteSignature{2}{$Symbol}{"Header"});
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012659 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012660 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012661 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012662 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012663 { # checking removed symbols
12664 next if($CompleteSignature{1}{$Symbol}{"Private"});
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030012665 next if(not $CompleteSignature{1}{$Symbol}{"Header"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012666 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012667 { # skip v-tables for templates, that should not be imported by applications
12668 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012669 if(my $CName = $VTableClass{$Symbol})
12670 {
12671 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12672 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012673 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012674 next;
12675 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012676 }
12677 }
12678 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012679 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012680 }
12681 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12682 { # symbols for pure virtual methods cannot be called by clients
12683 next;
12684 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012685 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012686 }
12687}
12688
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012689sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012690{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012691 my ($LibVersion, $V) = @_;
12692 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12693 return $Cache{"checkDump"}{$LibVersion}{$V};
12694 }
12695 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012696}
12697
12698sub detectAdded_H($)
12699{
12700 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012701 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12702 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012703 if($Level eq "Source")
12704 { # remove symbol version
12705 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12706 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012707
12708 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12709 { # skip artificial constructors
12710 next;
12711 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012712 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012713 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12714 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012715 next;
12716 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012717 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012718 next;
12719 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012720 if(not defined $CompleteSignature{1}{$Symbol}
12721 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12722 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012723 if($UsedDump{2}{"SrcBin"})
12724 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012725 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012726 { # support for old and different (!) ABI dumps
12727 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12728 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012729 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012730 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012731 {
12732 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12733 {
12734 if($Lang eq "C")
12735 { # support for old ABI dumps: missed extern "C" functions
12736 next;
12737 }
12738 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012739 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012740 else
12741 {
12742 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012743 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012744 next;
12745 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012746 }
12747 }
12748 }
12749 }
12750 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012751 }
12752 }
12753}
12754
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012755sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012756{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012757 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012758 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12759 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012760 if($Level eq "Source")
12761 { # remove symbol version
12762 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12763 $Symbol=$SN;
12764 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012765 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12766 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012767 next;
12768 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012769 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012770 next;
12771 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012772 if(not defined $CompleteSignature{2}{$Symbol}
12773 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012774 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012775 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012776 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012777 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012778 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012779 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12780 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012781 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012782 if($CheckHeadersOnly)
12783 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012784 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12785 {
12786 if($Lang eq "C")
12787 { # support for old ABI dumps: missed extern "C" functions
12788 next;
12789 }
12790 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012791 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012792 else
12793 {
12794 if(not link_symbol($Symbol, 1, "-Deps"))
12795 { # skip removed inline symbols
12796 next;
12797 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012798 }
12799 }
12800 }
12801 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012802 if(not checkDump(1, "2.15"))
12803 {
12804 if($Symbol=~/_IT_E\Z/)
12805 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12806 next;
12807 }
12808 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012809 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12810 {
12811 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12812 {
12813 if(defined $Constants{2}{$Short})
12814 {
12815 my $Val = $Constants{2}{$Short}{"Value"};
12816 if(defined $Func_ShortName{2}{$Val})
12817 { # old name defined to new
12818 next;
12819 }
12820 }
12821 }
12822
12823 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012824 $RemovedInt{$Level}{$Symbol} = 1;
12825 if($Level eq "Source")
12826 { # search for a source-compatible equivalent
12827 setAlternative($Symbol, $Level);
12828 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012829 }
12830 }
12831}
12832
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012833sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012834{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012835 my $Level = $_[0];
12836 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012837 { # checking added symbols
12838 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012839 next if($CompleteSignature{2}{$Symbol}{"Private"});
12840 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012841 if($Level eq "Binary")
12842 {
12843 if($CompleteSignature{2}{$Symbol}{"InLine"})
12844 {
12845 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12846 { # skip inline non-virtual functions
12847 next;
12848 }
12849 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012850 }
12851 else
12852 { # Source
12853 if($SourceAlternative_B{$Symbol}) {
12854 next;
12855 }
12856 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012857 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012858 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012859 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012860 { # checking removed symbols
12861 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012862 next if($CompleteSignature{1}{$Symbol}{"Private"});
12863 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012864 if($Level eq "Binary")
12865 {
12866 if($CompleteSignature{1}{$Symbol}{"InLine"})
12867 {
12868 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
12869 { # skip inline non-virtual functions
12870 next;
12871 }
12872 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012873 }
12874 else
12875 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012876 if(my $Alt = $SourceAlternative{$Symbol})
12877 {
12878 if(defined $CompleteSignature{1}{$Alt}
12879 and $CompleteSignature{1}{$Symbol}{"Const"})
12880 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012881 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012882 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012883 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012884 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012885 }
12886 else
12887 { # do NOT show removed symbol
12888 next;
12889 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012890 }
12891 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012892 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012893 }
12894}
12895
12896sub addParamNames($)
12897{
12898 my $LibraryVersion = $_[0];
12899 return if(not keys(%AddIntParams));
12900 my $SecondVersion = $LibraryVersion==1?2:1;
12901 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
12902 {
12903 next if(not keys(%{$AddIntParams{$Interface}}));
12904 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012905 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012906 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
12907 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012908 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012909 if(defined $CompleteSignature{$SecondVersion}{$Interface}
12910 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
12911 {
12912 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
12913 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12914 }
12915 }
12916 else {
12917 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12918 }
12919 }
12920 }
12921 }
12922}
12923
12924sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012925{ # detect changed typedefs to show
12926 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012927 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
12928 {
12929 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012930 my $BName1 = $Typedef_BaseName{1}{$Typedef};
12931 if(not $BName1 or isAnon($BName1)) {
12932 next;
12933 }
12934 my $BName2 = $Typedef_BaseName{2}{$Typedef};
12935 if(not $BName2 or isAnon($BName2)) {
12936 next;
12937 }
12938 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012939 $ChangedTypedef{$Typedef} = 1;
12940 }
12941 }
12942}
12943
12944sub get_symbol_suffix($$)
12945{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012946 my ($Symbol, $Full) = @_;
12947 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040012948 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012949 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012950 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012951 if(not $Full) {
12952 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
12953 }
12954 return $Suffix;
12955}
12956
12957sub get_symbol_prefix($$)
12958{
12959 my ($Symbol, $LibVersion) = @_;
12960 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
12961 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12962 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012963 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012964 }
12965 return $ShortName;
12966}
12967
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012968sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012969{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012970 my $Symbol = $_[0];
12971 my $PSymbol = $Symbol;
12972 if(not defined $CompleteSignature{2}{$PSymbol}
12973 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
12974 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
12975 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012976 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012977 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012978 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012979 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012980 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
12981 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012982 {
12983 if(defined $CompleteSignature{2}{$PSymbol}
12984 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12985 {
12986 $SourceAlternative{$Symbol} = $PSymbol;
12987 $SourceAlternative_B{$PSymbol} = $Symbol;
12988 if(not defined $CompleteSignature{1}{$PSymbol}
12989 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12990 $SourceReplacement{$Symbol} = $PSymbol;
12991 }
12992 }
12993 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012994 }
12995 else
12996 {
12997 foreach my $Sp ("KV", "VK", "K", "V")
12998 {
12999 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13000 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13001 {
13002 if(defined $CompleteSignature{2}{$PSymbol}
13003 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13004 {
13005 $SourceAlternative{$Symbol} = $PSymbol;
13006 $SourceAlternative_B{$PSymbol} = $Symbol;
13007 if(not defined $CompleteSignature{1}{$PSymbol}
13008 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13009 $SourceReplacement{$Symbol} = $PSymbol;
13010 }
13011 }
13012 }
13013 $PSymbol = $Symbol;
13014 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013015 }
13016 }
13017 }
13018 return "";
13019}
13020
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013021sub getSymKind($$)
13022{
13023 my ($Symbol, $LibVersion) = @_;
13024 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13025 {
13026 return "Global_Data";
13027 }
13028 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13029 {
13030 return "Method";
13031 }
13032 return "Function";
13033}
13034
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013035sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013036{
13037 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013038 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013039
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013040 mergeBases($Level);
13041
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013042 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013043 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013044 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013045 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013046 next;
13047 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013048 if(defined $CompleteSignature{1}{$Symbol}
13049 and $CompleteSignature{1}{$Symbol}{"Header"})
13050 { # double-check added symbol
13051 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013052 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013053 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013054 next;
13055 }
13056 if($Symbol=~/\A(_Z|\?)/)
13057 { # C++
13058 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13059 }
13060 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13061 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013062 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13063 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013064 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013065 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013066 {
13067 if($TName_Tid{1}{$AffectedClass_Name})
13068 { # class should exist in previous version
13069 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13070 { # old v-table is NOT copied by old applications
13071 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13072 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013073 "Target"=>get_Signature($Symbol, 2),
13074 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013075 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013076 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013077 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013078 }
13079 }
13080 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013081 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13082 { # check all removed exported symbols
13083 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013084 next;
13085 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013086 if(defined $CompleteSignature{2}{$Symbol}
13087 and $CompleteSignature{2}{$Symbol}{"Header"})
13088 { # double-check removed symbol
13089 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013090 }
13091 if($CompleteSignature{1}{$Symbol}{"Private"})
13092 { # skip private methods
13093 next;
13094 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013095 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013096 next;
13097 }
13098 $CheckedSymbols{$Level}{$Symbol} = 1;
13099 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13100 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013101 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13102 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013103 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013104 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13105 {
13106 if($TName_Tid{2}{$AffectedClass_Name})
13107 { # class should exist in newer version
13108 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13109 { # old v-table is NOT copied by old applications
13110 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13111 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013112 "Target"=>get_Signature($OverriddenMethod, 1),
13113 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013114 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013115 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013116 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013117 }
13118 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013119 if($Level eq "Binary"
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030013120 and $OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013121 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013122 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013123 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013124 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013125 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013126 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013127 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013128 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013129 {
13130 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13131 "Target"=>$tr_name{$Symbol},
13132 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013133 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013134 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013135 else
13136 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013137 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013138 "Target"=>$tr_name{$Symbol},
13139 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013140 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013141 }
13142 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013143 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013144 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013145 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013146 {
13147 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13148 "Target"=>$tr_name{$Symbol},
13149 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013150 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013151 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013152 else
13153 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013154 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013155 "Target"=>$tr_name{$Symbol},
13156 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013157 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013158 }
13159 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013160 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13161 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13162 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13163 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13164 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013165 {
13166 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013167 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013168 $ProblemType = "Global_Data_Symbol_Changed_Type";
13169 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013170 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13171 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013172 "Old_Type"=>$RTName1,
13173 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013174 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013175 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013176 }
13177 }
13178 }
13179 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013180 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013181 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013182 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013183 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013184 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013185 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013186 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013187 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13188 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013189 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013190 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013191 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013192 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013193 }
13194 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013195 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13196 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013197 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013198 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013199 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013200 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013201 }
13202 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013203 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013204 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013205 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013206 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013207 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013208 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013209 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013210 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013211 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013212 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013213 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013214 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013215 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013216 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013217 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013218 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013219 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013220 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013221 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013222 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013223 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013224 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013225 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013226 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013227 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013228 { # "volatile" to non-"volatile"
13229
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013230 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013231 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013232 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013233 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013234 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013235 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013236 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013237 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013238 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013239 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013240 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013241 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013242 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013243 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013244 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013245 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013246 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013247 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13248 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013249 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013250 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013251 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013252 }
13253 }
13254 }
13255 }
13256 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013257 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13258 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013259 $CurrentSymbol = $Symbol;
13260
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013261 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13262 if($Level eq "Source")
13263 { # remove symbol version
13264 $Symbol=$SN;
13265 }
13266 else
13267 { # Binary
13268 if(not $SV)
13269 { # symbol without version
13270 if(my $VSym = $SymVer{1}{$Symbol})
13271 { # the symbol is linked with versioned symbol
13272 if($CompleteSignature{2}{$VSym}{"MnglName"})
13273 { # show report for symbol@ver only
13274 next;
13275 }
13276 elsif(not link_symbol($VSym, 2, "-Deps"))
13277 { # changed version: sym@v1 to sym@v2
13278 # do NOT show report for symbol
13279 next;
13280 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013281 }
13282 }
13283 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013284 my $PSymbol = $Symbol;
13285 if($Level eq "Source"
13286 and my $S = $SourceReplacement{$Symbol})
13287 { # take a source-compatible replacement function
13288 $PSymbol = $S;
13289 }
13290 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013291 { # private symbols
13292 next;
13293 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013294 if(not defined $CompleteSignature{1}{$Symbol}
13295 or not defined $CompleteSignature{2}{$PSymbol})
13296 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013297 next;
13298 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013299 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13300 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13301 { # no mangled name
13302 next;
13303 }
13304 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13305 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013306 { # without a header
13307 next;
13308 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013309
13310 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13311 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13312 { # became pure
13313 next;
13314 }
13315 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13316 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13317 { # became non-pure
13318 next;
13319 }
13320
13321 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13322 { # exported, target, inline virtual and pure virtual
13323 next;
13324 }
13325 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13326 { # exported, target, inline virtual and pure virtual
13327 next;
13328 }
13329
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013330 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013331 {
13332 if($CompleteSignature{1}{$Symbol}{"Data"}
13333 and $CompleteSignature{2}{$PSymbol}{"Data"})
13334 {
13335 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13336 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13337 if(defined $Value1)
13338 {
13339 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13340 if(defined $Value2)
13341 {
13342 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13343 if($Value1 ne $Value2)
13344 {
13345 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13346 "Old_Value"=>$Value1,
13347 "New_Value"=>$Value2,
13348 "Target"=>get_Signature($Symbol, 1) );
13349 }
13350 }
13351 }
13352 }
13353 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013354
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013355 if($CompleteSignature{2}{$PSymbol}{"Private"})
13356 {
13357 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13358 "Target"=>get_Signature_M($PSymbol, 2) );
13359 }
13360 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13361 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13362 {
13363 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13364 "Target"=>get_Signature_M($PSymbol, 2) );
13365 }
13366 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13367 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13368 {
13369 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13370 "Target"=>get_Signature_M($PSymbol, 2) );
13371 }
13372
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013373 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013374 mergeVirtualTables($Symbol, $Level);
13375
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013376 if($COMPILE_ERRORS)
13377 { # if some errors occurred at the compiling stage
13378 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013379 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013380 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013381 { # missed information about parameters in newer version
13382 next;
13383 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013384 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013385 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013386 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013387 next;
13388 }
13389 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013390 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013391 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013392 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013393 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13394 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013395 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13396 "Target"=>get_Signature($Symbol, 1)
13397 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013398 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013399 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013400 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13401 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013402 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013403 "Target"=>get_Signature($Symbol, 1)
13404 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013405 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013406 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13407 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013408 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013409 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013410 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013411 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13412 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13413 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013414 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013415 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013416 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13417 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013418 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013419 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013420 my $ProblemType = "Virtual_Method_Position";
13421 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13422 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013423 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013424 if(isUsedClass($Class_Id, 1, $Level))
13425 {
13426 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013427 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013428 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013429 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13430 next;
13431 }
13432 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013433 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013434 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13435 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013436 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013437 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013438 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013439 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013440 }
13441 }
13442 }
13443 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013444 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13445 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013446 { # do NOT check type changes in pure virtuals
13447 next;
13448 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013449 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013450 if($Symbol=~/\A(_Z|\?)/
13451 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013452 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013453 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013454 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013455 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013456 }
13457 }
13458 else
13459 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013460 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013461 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013462 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013463 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13464 last if($PType2_Name eq "...");
13465 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13466 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013467 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013468 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013469 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013470 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13471 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013472 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13473 $ParamPos_Prev = "lost";
13474 }
13475 }
13476 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013477 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013478 }
13479 if($ParamPos_Prev eq "lost")
13480 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013481 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013482 {
13483 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013484 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013485 $ProblemType = "Added_Unnamed_Parameter";
13486 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013487 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013488 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013489 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013490 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013491 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013492 }
13493 else
13494 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013495 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013496 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013497 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013498 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13499 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013500 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013501 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013502 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013503 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013504 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013505 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013506 "Param_Type"=>$PType2_Name,
13507 "Old_Value"=>$PName_Old,
13508 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013509 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013510 }
13511 }
13512 else
13513 {
13514 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013515 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013516 $ProblemType = "Added_Middle_Unnamed_Parameter";
13517 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013518 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013519 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013520 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013521 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013522 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013523 }
13524 }
13525 }
13526 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013527 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013528 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013529 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013530 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013531 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013532 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013533 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013534 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013535 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013536 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13537 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013538 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013539 }
13540 }
13541 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013542 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013543 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013544 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013545 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13546 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013547 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13548 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013549 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013550 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013551 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013552 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13553 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013554 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13555 $ParamPos_New = "lost";
13556 }
13557 }
13558 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013559 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013560 }
13561 if($ParamPos_New eq "lost")
13562 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013563 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013564 {
13565 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013566 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013567 $ProblemType = "Removed_Unnamed_Parameter";
13568 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013569 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013570 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013571 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013572 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013573 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013574 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013575 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013576 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013577 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013578 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013579 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013580 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013581 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013582 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013583 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013584 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013585 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013586 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013587 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013588 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013589 "Old_Value"=>$PName,
13590 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013591 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013592 }
13593 }
13594 else
13595 {
13596 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013597 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013598 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13599 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013600 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013601 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013602 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013603 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013604 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013605 }
13606 }
13607 }
13608 }
13609 }
13610 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013611 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13612 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013613 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013614
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013615 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013616 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013617 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13618 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013619 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013620
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013621 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013622 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013623 if($SubProblemType eq "Return_Type_And_Size") {
13624 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13625 }
13626 elsif($SubProblemType eq "Return_Type_Format") {
13627 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13628 }
13629 else {
13630 $ProblemTypes{"Global_Data_Type"} = 1;
13631 }
13632
13633 # quals
13634 if($SubProblemType eq "Return_Type"
13635 or $SubProblemType eq "Return_Type_And_Size"
13636 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013637 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013638 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13639 { # const to non-const
13640 if($RR==2) {
13641 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13642 }
13643 else {
13644 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13645 }
13646 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013647 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013648 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13649 { # non-const to const
13650 if($RA==2) {
13651 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13652 }
13653 else {
13654 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13655 }
13656 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013657 }
13658 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013659 }
13660 else
13661 {
13662 # quals
13663 if($SubProblemType eq "Return_Type"
13664 or $SubProblemType eq "Return_Type_And_Size"
13665 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013666 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013667 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013668 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013669 if(addedQual($Old_Value, $New_Value, "volatile"))
13670 {
13671 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13672 if($Level ne "Source"
13673 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13674 $ProblemTypes{"Return_Type"} = 1;
13675 }
13676 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013677 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013678 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13679 {
13680 if($RA==2) {
13681 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13682 }
13683 else {
13684 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13685 }
13686 if($Level ne "Source"
13687 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13688 $ProblemTypes{"Return_Type"} = 1;
13689 }
13690 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013691 }
13692 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013693 if($Level eq "Binary"
13694 and not $CompleteSignature{1}{$Symbol}{"Data"})
13695 {
13696 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13697 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13698 { # if one of the architectures is unknown
13699 # then set other arhitecture to unknown too
13700 ($Arch1, $Arch2) = ("unknown", "unknown");
13701 }
13702 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013703 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013704 {
13705 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13706 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13707 }
13708 else
13709 {
13710 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13711 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13712 }
13713
13714 if($SubProblemType eq "Return_Type_Became_Void")
13715 {
13716 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13717 { # parameters stack has been affected
13718 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013719 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013720 }
13721 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013722 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013723 }
13724 }
13725 }
13726 elsif($SubProblemType eq "Return_Type_From_Void")
13727 {
13728 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13729 { # parameters stack has been affected
13730 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013731 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013732 }
13733 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013734 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013735 }
13736 }
13737 }
13738 elsif($SubProblemType eq "Return_Type"
13739 or $SubProblemType eq "Return_Type_And_Size"
13740 or $SubProblemType eq "Return_Type_Format")
13741 {
13742 if($Conv1{"Method"} ne $Conv2{"Method"})
13743 {
13744 if($Conv1{"Method"} eq "stack")
13745 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013746 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013747 }
13748 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013749 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013750 }
13751 }
13752 else
13753 {
13754 if($Conv1{"Method"} eq "reg")
13755 {
13756 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13757 {
13758 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013759 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013760 }
13761 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013762 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013763 }
13764 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013765 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013766 }
13767 }
13768 }
13769 }
13770 }
13771 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013772
13773 if(not keys(%ProblemTypes))
13774 { # default
13775 $ProblemTypes{$SubProblemType} = 1;
13776 }
13777
13778 foreach my $ProblemType (keys(%ProblemTypes))
13779 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013780 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013781 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013782 }
13783 if($ReturnType1_Id and $ReturnType2_Id)
13784 {
13785 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013786 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
13787
13788 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013789
13790 if($CompleteSignature{1}{$Symbol}{"Data"})
13791 {
13792 if($Level eq "Binary")
13793 {
13794 if(get_PLevel($ReturnType1_Id, 1)==0)
13795 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013796 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013797 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013798
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013799 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
13800 {
13801 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040013802 {
13803 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
13804 {
13805 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
13806 last;
13807 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013808 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013809 }
13810 }
13811 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013812 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013813 {
13814 if(defined $GlobalDataObject{1}{$Symbol}
13815 and defined $GlobalDataObject{2}{$Symbol})
13816 {
13817 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13818 my $New_Size = $GlobalDataObject{2}{$Symbol};
13819 if($Old_Size!=$New_Size)
13820 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013821 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013822 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013823 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013824 }
13825 }
13826 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013827 }
13828 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013829
13830 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013831 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013832 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013833 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013834 my $NewLocation = "retval";
13835 if($SubLocation and $SubLocation ne "retval") {
13836 $NewLocation = "retval->".$SubLocation;
13837 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013838 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
13839 }
13840 }
13841
13842 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
13843 {
13844 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
13845 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040013846 my $NewLocation = "retval";
13847 if($SubLocation and $SubLocation ne "retval") {
13848 $NewLocation = "retval->".$SubLocation;
13849 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013850 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013851 }
13852 }
13853 }
13854
13855 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013856 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13857 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13858 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013859 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013860 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013861 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13862 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013863 if($ThisPtr1_Id and $ThisPtr2_Id)
13864 {
13865 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013866 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
13867 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013868 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013869 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013870 {
13871 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013872 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013873 }
13874 }
13875 }
13876 }
13877 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013878 if($Level eq "Binary") {
13879 mergeVTables($Level);
13880 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013881 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
13882 $CheckedSymbols{$Level}{$Symbol} = 1;
13883 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013884}
13885
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013886sub rmQuals($$)
13887{
13888 my ($Value, $Qual) = @_;
13889 if(not $Qual) {
13890 return $Value;
13891 }
13892 if($Qual eq "all")
13893 { # all quals
13894 $Qual = "const|volatile|restrict";
13895 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013896 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013897 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013898 }
13899 return $Value;
13900}
13901
13902sub cmpBTypes($$$$)
13903{
13904 my ($T1, $T2, $V1, $V2) = @_;
13905 $T1 = uncover_typedefs($T1, $V1);
13906 $T2 = uncover_typedefs($T2, $V2);
13907 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
13908}
13909
13910sub addedQual($$$)
13911{
13912 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013913 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013914}
13915
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013916sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013917{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013918 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013919 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013920}
13921
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013922sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013923{
13924 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
13925 $Old_Value = uncover_typedefs($Old_Value, $V1);
13926 $New_Value = uncover_typedefs($New_Value, $V2);
13927 if($Old_Value eq $New_Value)
13928 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013929 return 0;
13930 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013931 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013932 { # without a qual
13933 return 0;
13934 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013935 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013936 { # became non-qual
13937 return 1;
13938 }
13939 else
13940 {
13941 my @BQ1 = getQualModel($Old_Value, $Qual);
13942 my @BQ2 = getQualModel($New_Value, $Qual);
13943 foreach (0 .. $#BQ1)
13944 { # removed qual
13945 if($BQ1[$_]==1
13946 and $BQ2[$_]!=1)
13947 {
13948 return 2;
13949 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013950 }
13951 }
13952 return 0;
13953}
13954
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013955sub getQualModel($$)
13956{
13957 my ($Value, $Qual) = @_;
13958 if(not $Qual) {
13959 return $Value;
13960 }
13961
13962 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013963 while($Value=~/(\w+)/ and $1 ne $Qual) {
13964 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013965 }
13966 $Value=~s/[^\*\&\w]+//g;
13967
13968 # modeling
13969 # int*const*const == 011
13970 # int**const == 001
13971 my @Model = ();
13972 my @Elems = split(/[\*\&]/, $Value);
13973 if(not @Elems) {
13974 return (0);
13975 }
13976 foreach (@Elems)
13977 {
13978 if($_ eq $Qual) {
13979 push(@Model, 1);
13980 }
13981 else {
13982 push(@Model, 0);
13983 }
13984 }
13985
13986 return @Model;
13987}
13988
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013989my %StringTypes = map {$_=>1} (
13990 "char*",
13991 "char const*"
13992);
13993
13994my %CharTypes = map {$_=>1} (
13995 "char",
13996 "char const"
13997);
13998
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013999sub showVal($$$)
14000{
14001 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014002 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014003 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014004 if(substr($Value, 0, 2) eq "_Z")
14005 {
14006 if(my $Unmangled = $tr_name{$Value}) {
14007 return $Unmangled;
14008 }
14009 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014010 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014011 { # strings
14012 return "\"$Value\"";
14013 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014014 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014015 { # characters
14016 return "\'$Value\'";
14017 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014018 if($Value eq "")
14019 { # other
14020 return "\'\'";
14021 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014022 return $Value;
14023}
14024
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014025sub getRegs($$$)
14026{
14027 my ($LibVersion, $Symbol, $Pos) = @_;
14028
14029 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14030 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014031 my %Regs = ();
14032 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14033 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014034 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014035 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14036 }
14037 }
14038
14039 return join(", ", sort keys(%Regs));
14040 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014041 elsif(defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}
14042 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}
14043 and not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{0}{"offset"})
14044 {
14045 return "unknown";
14046 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014047
14048 return undef;
14049}
14050
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014051sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014052{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014053 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014054 if(not $Symbol) {
14055 return;
14056 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014057 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14058 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14059 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14060 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014061 if(not $PType1_Id
14062 or not $PType2_Id) {
14063 return;
14064 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014065
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014066 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014067 { # do not merge "this"
14068 if($PName1 eq "this" or $PName2 eq "this") {
14069 return;
14070 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014071 }
14072
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014073 my %Type1 = get_Type($PType1_Id, 1);
14074 my %Type2 = get_Type($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014075
14076 my %PureType1 = get_PureType($PType1_Id, $TypeInfo{1});
14077
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014078 my %BaseType1 = get_BaseType($PType1_Id, 1);
14079 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014080
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014081 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014082
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014083 if($Level eq "Binary")
14084 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014085 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014086 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14087 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14088 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14089 {
14090 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014091 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014092 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014093 }
14094 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14095 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14096 {
14097 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014098 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014099 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014100 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014101 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014102
14103 if(defined $UsedDump{1}{"DWARF"}
14104 and defined $UsedDump{2}{"DWARF"})
14105 {
14106 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14107 {
14108 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14109 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014110
14111 if($Old_Regs ne "unknown"
14112 and $New_Regs ne "unknown")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014113 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014114 if($Old_Regs and $New_Regs)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014115 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014116 if($Old_Regs ne $New_Regs)
14117 {
14118 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14119 "Target"=>$PName1,
14120 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14121 "Old_Value"=>$Old_Regs,
14122 "New_Value"=>$New_Regs );
14123 }
14124 }
14125 elsif($Old_Regs and not $New_Regs)
14126 {
14127 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014128 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014129 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014130 "Old_Value"=>$Old_Regs );
14131 }
14132 elsif(not $Old_Regs and $New_Regs)
14133 {
14134 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14135 "Target"=>$PName1,
14136 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014137 "New_Value"=>$New_Regs );
14138 }
14139 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014140
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014141 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14142 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14143 {
14144 if($Old_Offset ne $New_Offset)
14145 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014146 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14147 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14148
14149 $Old_Offset = $Old_Offset - $Start1;
14150 $New_Offset = $New_Offset - $Start2;
14151
14152 if($Old_Offset ne $New_Offset)
14153 {
14154 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14155 "Target"=>$PName1,
14156 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14157 "Old_Value"=>$Old_Offset,
14158 "New_Value"=>$New_Offset );
14159 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014160 }
14161 }
14162 }
14163 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014164 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014165 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14166 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014167 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014168 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014169 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14170 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014171 if(not checkDump(1, "2.13")
14172 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014173 { # support for old ABI dumps
14174 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014175 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014176 if($PureType1{"Name"} eq "bool"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014177 and $Value_Old eq "false" and $Value_New eq "0")
14178 { # int class::method ( bool p = 0 );
14179 # old ABI dumps: "false"
14180 # new ABI dumps: "0"
14181 $Value_Old = "0";
14182 }
14183 }
14184 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014185 if(not checkDump(1, "2.18")
14186 and checkDump(2, "2.18"))
14187 { # support for old ABI dumps
14188 if(not defined $Value_Old
14189 and substr($Value_New, 0, 2) eq "_Z") {
14190 $Value_Old = $Value_New;
14191 }
14192 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014193 if(defined $Value_Old)
14194 {
14195 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14196 if(defined $Value_New)
14197 {
14198 $Value_New = showVal($Value_New, $PType2_Id, 2);
14199 if($Value_Old ne $Value_New)
14200 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014201 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014202 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014203 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014204 "Old_Value"=>$Value_Old,
14205 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014206 }
14207 }
14208 else
14209 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014210 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014211 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014212 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014213 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014214 }
14215 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014216 elsif(defined $Value_New)
14217 {
14218 $Value_New = showVal($Value_New, $PType2_Id, 2);
14219 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14220 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014221 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014222 "New_Value"=>$Value_New );
14223 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014224 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014225
14226 if($ChkRnmd)
14227 {
14228 if($PName1 and $PName2 and $PName1 ne $PName2
14229 and $PType1_Id!=-1 and $PType2_Id!=-1
14230 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14231 { # except unnamed "..." value list (Id=-1)
14232 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14233 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014234 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014235 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14236 "Old_Value"=>$PName1,
14237 "New_Value"=>$PName2,
14238 "New_Signature"=>get_Signature($Symbol, 2) );
14239 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014240 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014241
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014242 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014243 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014244
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014245 foreach my $SubProblemType (keys(%SubProblems))
14246 { # add new problems, remove false alarms
14247 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14248 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014249
14250 # quals
14251 if($SubProblemType eq "Parameter_Type"
14252 or $SubProblemType eq "Parameter_Type_And_Size"
14253 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014254 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014255 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014256 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014257 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014258 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014259 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014260 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14261 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14262 }
14263 }
14264 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14265 {
14266 if(removedQual($Old_Value, $New_Value, "volatile")) {
14267 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014268 }
14269 }
14270 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14271 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14272 { # int to "int const"
14273 delete($SubProblems{$SubProblemType});
14274 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014275 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014276 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14277 { # "int const" to int
14278 delete($SubProblems{$SubProblemType});
14279 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014280 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14281 { # "const" to non-"const"
14282 if($RR==2) {
14283 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14284 }
14285 else {
14286 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14287 }
14288 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014289 }
14290 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014291
14292 if($Level eq "Source")
14293 {
14294 foreach my $SubProblemType (keys(%SubProblems))
14295 {
14296 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14297 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14298
14299 if($SubProblemType eq "Parameter_Type")
14300 {
14301 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14302 delete($SubProblems{$SubProblemType});
14303 }
14304 }
14305 }
14306 }
14307
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014308 foreach my $SubProblemType (keys(%SubProblems))
14309 { # modify/register problems
14310 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14311 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014312 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14313 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014314
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014315 my $NewProblemType = $SubProblemType;
14316 if($Old_Value eq "..." and $New_Value ne "...")
14317 { # change from "..." to "int"
14318 if($ParamPos1==0)
14319 { # ISO C requires a named argument before "..."
14320 next;
14321 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014322 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014323 }
14324 elsif($New_Value eq "..." and $Old_Value ne "...")
14325 { # change from "int" to "..."
14326 if($ParamPos2==0)
14327 { # ISO C requires a named argument before "..."
14328 next;
14329 }
14330 $NewProblemType = "Parameter_Became_VaList";
14331 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014332 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014333 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014334 {
14335 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014336 if($Arch1 eq "unknown"
14337 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014338 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014339 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014340 ($Arch1, $Arch2) = ("unknown", "unknown");
14341 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014342 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014343 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014344 { # real
14345 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14346 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14347 }
14348 else
14349 { # model
14350 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14351 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14352 }
14353 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014354 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014355 if($Conv1{"Method"} eq "stack")
14356 {
14357 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14358 $NewProblemType = "Parameter_Type_And_Stack";
14359 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014360 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014361 elsif($Conv1{"Method"} eq "reg")
14362 {
14363 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14364 $NewProblemType = "Parameter_Type_And_Register";
14365 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014366 }
14367 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030014368 elsif($Conv1{"Method"} ne "unknown"
14369 and $Conv2{"Method"} ne "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014370 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014371 if($Conv1{"Method"} eq "stack") {
14372 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014373 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014374 elsif($Conv1{"Method"} eq "register") {
14375 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014376 }
14377 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014378 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14379 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014380 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014381 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014382 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014383 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014384 "New_Signature"=>get_Signature($Symbol, 2) );
14385 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014386 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014387
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014388 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014389
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014390 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014391 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14392 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014393 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014394 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014395 {
14396 my $NewProblemType = $SubProblemType;
14397 if($SubProblemType eq "DataType_Size")
14398 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030014399 if($PureType1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014400 { # stack has been affected
14401 $NewProblemType = "DataType_Size_And_Stack";
14402 }
14403 }
14404 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014405 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014406 }
14407 }
14408}
14409
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014410sub find_ParamPair_Pos_byName($$$)
14411{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014412 my ($Name, $Symbol, $LibVersion) = @_;
14413 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014414 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014415 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14416 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014417 {
14418 return $ParamPos;
14419 }
14420 }
14421 return "lost";
14422}
14423
14424sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14425{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014426 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014427 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014428 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014429 {
14430 next if($Order eq "backward" and $ParamPos>$MediumPos);
14431 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014432 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14433 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014434 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014435 push(@Positions, $ParamPos);
14436 }
14437 }
14438 return @Positions;
14439}
14440
14441sub getTypeIdByName($$)
14442{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014443 my ($TypeName, $LibVersion) = @_;
14444 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014445}
14446
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014447sub diffTypes($$$)
14448{
14449 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14450 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14451 }
14452 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14453 { # skip recursive declarations
14454 return 0;
14455 }
14456
14457 pushType($_[0], $_[1], \@RecurTypes_Diff);
14458 my $Diff = diffTypes_I(@_);
14459 pop(@RecurTypes_Diff);
14460
14461 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14462}
14463
14464sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014465{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014466 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014467
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014468 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14469 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014470
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014471 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14472 { # equal types
14473 return 0;
14474 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014475 if($Type1_Pure{"Name"} eq "void")
14476 { # from void* to something
14477 return 0;
14478 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014479 if($Type1_Pure{"Name"}=~/\*/
14480 or $Type2_Pure{"Name"}=~/\*/)
14481 { # compared in detectTypeChange()
14482 return 0;
14483 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014484
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014485 my %FloatType = map {$_=>1} (
14486 "float",
14487 "double",
14488 "long double"
14489 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014490
14491 my $T1 = $Type1_Pure{"Type"};
14492 my $T2 = $Type2_Pure{"Type"};
14493
14494 if($T1 eq "Struct"
14495 and $T2 eq "Class")
14496 { # compare as data structures
14497 $T2 = "Struct";
14498 }
14499
14500 if($T1 eq "Class"
14501 and $T2 eq "Struct")
14502 { # compare as data structures
14503 $T1 = "Struct";
14504 }
14505
14506 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014507 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014508 if($T1 eq "Intrinsic"
14509 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014510 { # "int" to "enum"
14511 return 0;
14512 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014513 elsif($T2 eq "Intrinsic"
14514 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014515 { # "enum" to "int"
14516 return 0;
14517 }
14518 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014519 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014520 # ...
14521 return 1;
14522 }
14523 }
14524 else
14525 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014526 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014527 {
14528 if($FloatType{$Type1_Pure{"Name"}}
14529 or $FloatType{$Type2_Pure{"Name"}})
14530 { # "float" to "double"
14531 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014532 if($Level eq "Source")
14533 { # Safe
14534 return 0;
14535 }
14536 else {
14537 return 1;
14538 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014539 }
14540 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014541 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014542 {
14543 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14544 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014545 if(not @Membs1
14546 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014547 { # private
14548 return 0;
14549 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014550 if($#Membs1!=$#Membs2)
14551 { # different number of elements
14552 return 1;
14553 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014554 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014555 {
14556 foreach my $Pos (@Membs1)
14557 { # compare elements by name and value
14558 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14559 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14560 { # different names
14561 return 1;
14562 }
14563 }
14564 }
14565 else
14566 {
14567 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014568 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014569 if($Level eq "Source")
14570 {
14571 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14572 { # different names
14573 return 1;
14574 }
14575 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014576
14577 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14578 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14579
14580 if($MT1{"Name"} ne $MT2{"Name"}
14581 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14582 {
14583 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14584 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14585
14586 if($PL1 ne $PL2)
14587 { # different pointer level
14588 return 1;
14589 }
14590
14591 # compare base types
14592 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14593 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14594
14595 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14596 { # different types
14597 return 1;
14598 }
14599 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014600 }
14601 }
14602 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014603 else
14604 {
14605 # TODO: arrays, etc.
14606 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014607 }
14608 return 0;
14609}
14610
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014611sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014612{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014613 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014614 if(not $Type1_Id or not $Type2_Id) {
14615 return ();
14616 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014617 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014618 my %Type1 = get_Type($Type1_Id, 1);
14619 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014620 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14621 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014622
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014623 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14624 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 +040014625
Andrey Ponomarenko86b503b2015-12-11 23:40:03 +030014626 if(defined $UsedDump{1}{"DWARF"})
14627 {
14628 if($Type1_Pure{"Name"} eq "__unknown__"
14629 or $Type2_Pure{"Name"} eq "__unknown__"
14630 or $Type1_Base{"Name"} eq "__unknown__"
14631 or $Type2_Base{"Name"} eq "__unknown__")
14632 { # Error ABI dump
14633 return ();
14634 }
14635 }
14636
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014637 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14638 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014639 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14640 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14641 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14642 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14643 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14644 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14645 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014646 if($Type1{"Name"} eq $Type2{"Name"})
14647 {
14648 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14649 { # will be reported in mergeTypes() as typedef problem
14650 return ();
14651 }
14652 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14653 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14654 if(%Typedef_1 and %Typedef_2)
14655 {
14656 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14657 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14658 { # const Typedef
14659 return ();
14660 }
14661 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014662 }
14663 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14664 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014665 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014666 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14667 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014668 {
14669 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14670 "Old_Value"=>$Type1_Base{"Name"},
14671 "New_Value"=>$Type2_Base{"Name"},
14672 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014673 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014674 }
14675 else
14676 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014677 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014678 { # format change
14679 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14680 "Old_Value"=>$Type1_Base{"Name"},
14681 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014682 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014683 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014684 }
14685 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14686 {
14687 %{$LocalProblems{$Prefix."_BaseType"}}=(
14688 "Old_Value"=>$Type1_Base{"Name"},
14689 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014690 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014691 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014692 }
14693 }
14694 }
14695 }
14696 elsif($Type1{"Name"} ne $Type2{"Name"})
14697 { # type change
14698 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14699 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014700 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014701 and $Type1_Pure{"Name"} eq "void")
14702 {
14703 %{$LocalProblems{"Return_Type_From_Void"}}=(
14704 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014705 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014706 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014707 elsif($Prefix eq "Return"
14708 and $Type2_Pure{"Name"} eq "void")
14709 {
14710 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14711 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014712 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014713 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014714 else
14715 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014716 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014717 and $Type1{"Size"} and $Type2{"Size"}
14718 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014719 {
14720 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14721 "Old_Value"=>$Type1{"Name"},
14722 "New_Value"=>$Type2{"Name"},
14723 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014724 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014725 }
14726 else
14727 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014728 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014729 { # format change
14730 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14731 "Old_Value"=>$Type1{"Name"},
14732 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014733 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014734 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014735 }
14736 elsif(tNameLock($Type1_Id, $Type2_Id))
14737 { # FIXME: correct this condition
14738 %{$LocalProblems{$Prefix."_Type"}}=(
14739 "Old_Value"=>$Type1{"Name"},
14740 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014741 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014742 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014743 }
14744 }
14745 }
14746 }
14747 }
14748 if($Type1_PLevel!=$Type2_PLevel)
14749 {
14750 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14751 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14752 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014753 if($Level eq "Source")
14754 {
14755 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014756 "Old_Value"=>$Type1_PLevel,
14757 "New_Value"=>$Type2_PLevel);
14758 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014759 else
14760 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014761 if($Type2_PLevel>$Type1_PLevel)
14762 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014763 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14764 "Old_Value"=>$Type1_PLevel,
14765 "New_Value"=>$Type2_PLevel);
14766 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014767 else
14768 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014769 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14770 "Old_Value"=>$Type1_PLevel,
14771 "New_Value"=>$Type2_PLevel);
14772 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014773 }
14774 }
14775 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014776 if($Type1_Pure{"Type"} eq "Array"
14777 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014778 { # base_type[N] -> base_type[N]
14779 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014780 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014781 foreach my $SubProblemType (keys(%SubProblems))
14782 {
14783 $SubProblemType=~s/_Type/_BaseType/g;
14784 next if(defined $LocalProblems{$SubProblemType});
14785 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14786 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14787 }
14788 }
14789 }
14790 return %LocalProblems;
14791}
14792
14793sub tNameLock($$)
14794{
14795 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014796 my $Changed = 0;
14797 if(differentDumps("G"))
14798 { # different GCC versions
14799 $Changed = 1;
14800 }
14801 elsif(differentDumps("V"))
14802 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014803 if(not checkDump(1, "2.20")
14804 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014805 { # latest names update
14806 # 2.6: added restrict qualifier
14807 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014808 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014809 $Changed = 1;
14810 }
14811 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014812
14813 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14814 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14815
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014816 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14817 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
14818
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014819 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014820 { # different formats
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014821 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014822 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014823 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014824 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014825 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014826 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014827 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014828 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014829 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14830 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14831 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014832 { # equal base types
14833 return 0;
14834 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014835
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014836 if(not checkDump(1, "2.13")
14837 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014838 { # broken array names in ABI dumps < 2.13
14839 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014840 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014841 return 0;
14842 }
14843 }
14844
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014845 if(not checkDump(1, "2.6")
14846 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014847 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014848 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014849 and $TN2=~/\brestrict\b/) {
14850 return 0;
14851 }
14852 }
14853
14854 if(not checkDump(1, "2.20")
14855 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014856 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014857 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14858 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014859 return 0;
14860 }
14861 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014862 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014863 else
14864 {
14865 # typedef struct {...} type_t
14866 # typedef struct type_t {...} type_t
14867 if(index($TN1, " ".$TN2)!=-1)
14868 {
14869 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
14870 return 0;
14871 }
14872 }
14873 if(index($TN2, " ".$TN1)!=-1)
14874 {
14875 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
14876 return 0;
14877 }
14878 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040014879
14880 if($TT1 eq "FuncPtr"
14881 and $TT2 eq "FuncPtr")
14882 {
14883 my $TN1_C = $TN1;
14884 my $TN2_C = $TN2;
14885
14886 $TN1_C=~s/\b(struct|union) //g;
14887 $TN2_C=~s/\b(struct|union) //g;
14888
14889 if($TN1_C eq $TN2_C) {
14890 return 0;
14891 }
14892 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014893 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014894
14895 my ($N1, $N2) = ($TN1, $TN2);
14896 $N1=~s/\b(struct|union) //g;
14897 $N2=~s/\b(struct|union) //g;
14898
14899 if($N1 eq $N2)
14900 { # QList<struct QUrl> and QList<QUrl>
14901 return 0;
14902 }
14903
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014904 return 1;
14905}
14906
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014907sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014908{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014909 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014910 if(defined $Cache{"differentDumps"}{$Check}) {
14911 return $Cache{"differentDumps"}{$Check};
14912 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014913 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014914 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014915 if($Check eq "G")
14916 {
14917 if(getGccVersion(1) ne getGccVersion(2))
14918 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014919 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014920 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014921 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014922 if($Check eq "V")
14923 {
14924 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
14925 formatVersion($UsedDump{2}{"V"}, 2))!=0)
14926 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014927 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014928 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014929 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014930 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014931 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014932}
14933
14934sub formatVersion($$)
14935{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014936 my ($V, $Digits) = @_;
14937 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014938 return join(".", splice(@Elems, 0, $Digits));
14939}
14940
14941sub htmlSpecChars($)
14942{
14943 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014944 if(not $Str) {
14945 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014946 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014947 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14948 $Str=~s/</&lt;/g;
14949 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
14950 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014951 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
14952 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014953 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014954 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014955 $Str=~s/\n/<br\/>/g;
14956 $Str=~s/\"/&quot;/g;
14957 $Str=~s/\'/&#39;/g;
14958 return $Str;
14959}
14960
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014961sub xmlSpecChars($)
14962{
14963 my $Str = $_[0];
14964 if(not $Str) {
14965 return $Str;
14966 }
14967
14968 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14969 $Str=~s/</&lt;/g;
14970 $Str=~s/>/&gt;/g;
14971
14972 $Str=~s/\"/&quot;/g;
14973 $Str=~s/\'/&#39;/g;
14974
14975 return $Str;
14976}
14977
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014978sub xmlSpecChars_R($)
14979{
14980 my $Str = $_[0];
14981 if(not $Str) {
14982 return $Str;
14983 }
14984
14985 $Str=~s/&amp;/&/g;
14986 $Str=~s/&lt;/</g;
14987 $Str=~s/&gt;/>/g;
14988
14989 $Str=~s/&quot;/"/g;
14990 $Str=~s/&#39;/'/g;
14991
14992 return $Str;
14993}
14994
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014995sub black_name($)
14996{
14997 my $Name = $_[0];
14998 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
14999}
15000
15001sub highLight_Signature($)
15002{
15003 my $Signature = $_[0];
15004 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15005}
15006
15007sub highLight_Signature_Italic_Color($)
15008{
15009 my $Signature = $_[0];
15010 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15011}
15012
15013sub separate_symbol($)
15014{
15015 my $Symbol = $_[0];
15016 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15017 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15018 ($Name, $Spec, $Ver) = ($1, $2, $3);
15019 }
15020 return ($Name, $Spec, $Ver);
15021}
15022
15023sub cut_f_attrs($)
15024{
15025 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15026 return $2;
15027 }
15028 return "";
15029}
15030
15031sub highLight_Signature_PPos_Italic($$$$$)
15032{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015033 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15034 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015035 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15036 my $Return = "";
15037 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15038 $Return = $2;
15039 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015040 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015041 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015042 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015043 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015044 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015045 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015046 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015047 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015048 }
15049 return $Signature;
15050 }
15051 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15052 $Begin.=" " if($Begin!~/ \Z/);
15053 $End = cut_f_attrs($Signature);
15054 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015055 my ($Short, $Params) = split_Signature($Signature);
15056 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015057 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015058 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015059 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015060 $Part=~s/\A\s+|\s+\Z//g;
15061 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15062 if($Part=~/\([\*]+(\w+)\)/i) {
15063 $ParamName = $1;#func-ptr
15064 }
15065 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15066 $ParamName = $1;
15067 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015068 if(not $ParamName)
15069 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015070 push(@Parts, $Part_Styled);
15071 next;
15072 }
15073 if($ItalicParams and not $TName_Tid{1}{$Part}
15074 and not $TName_Tid{2}{$Part})
15075 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015076 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015077 if($Param_Pos ne ""
15078 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015079 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015080 }
15081 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015082 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015083 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015084 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015085 }
15086 $Part_Styled=~s/,(\w)/, $1/g;
15087 push(@Parts, $Part_Styled);
15088 }
15089 if(@Parts)
15090 {
15091 foreach my $Num (0 .. $#Parts)
15092 {
15093 if($Num==$#Parts)
15094 { # add ")" to the last parameter
15095 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15096 }
15097 elsif(length($Parts[$Num])<=45) {
15098 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15099 }
15100 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015101 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015102 }
15103 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015104 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015105 }
15106 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015107 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015108 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015109 $Signature=~s!\[\]![&#160;]!g;
15110 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015111 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15112 if($SymbolVersion) {
15113 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15114 }
15115 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015116}
15117
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015118sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015119{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015120 my $Signature = $_[0];
15121 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15122 {
15123 $Signature=~s/\A\Q$ShortName\E\(//g;
15124 cut_f_attrs($Signature);
15125 $Signature=~s/\)\Z//;
15126 return ($ShortName, $Signature);
15127 }
15128
15129 # error
15130 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015131}
15132
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015133sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015134{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015135 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015136 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015137 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15138 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015139 foreach my $Pos (0 .. length($Params) - 1)
15140 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015141 my $S = substr($Params, $Pos, 1);
15142 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015143 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015144 }
15145 if($S eq "," and
15146 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015147 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015148 if($Comma)
15149 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015150 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015151 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015152 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015153 }
15154 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015155 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015156 }
15157 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015158 if(not $Sp)
15159 { # remove spaces
15160 foreach (@Parts)
15161 {
15162 s/\A //g;
15163 s/ \Z//g;
15164 }
15165 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015166 return @Parts;
15167}
15168
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015169sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015170{
15171 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015172 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015173 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015174 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15175 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015176 $Center+=length($1);
15177 }
15178 foreach my $Pos (0 .. length($Sign)-1)
15179 {
15180 my $S = substr($Sign, $Pos, 1);
15181 if($S eq $Target)
15182 {
15183 if($B{"("}==$B{")"}
15184 and $B{"<"}==$B{">"}) {
15185 return $Center;
15186 }
15187 }
15188 if(defined $B{$S}) {
15189 $B{$S}+=1;
15190 }
15191 $Center+=1;
15192 }
15193 return 0;
15194}
15195
15196sub appendFile($$)
15197{
15198 my ($Path, $Content) = @_;
15199 return if(not $Path);
15200 if(my $Dir = get_dirname($Path)) {
15201 mkpath($Dir);
15202 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015203 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015204 print FILE $Content;
15205 close(FILE);
15206}
15207
15208sub writeFile($$)
15209{
15210 my ($Path, $Content) = @_;
15211 return if(not $Path);
15212 if(my $Dir = get_dirname($Path)) {
15213 mkpath($Dir);
15214 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015215 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015216 print FILE $Content;
15217 close(FILE);
15218}
15219
15220sub readFile($)
15221{
15222 my $Path = $_[0];
15223 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015224 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015225 local $/ = undef;
15226 my $Content = <FILE>;
15227 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015228 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015229 $Content=~s/\r/\n/g;
15230 }
15231 return $Content;
15232}
15233
15234sub get_filename($)
15235{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015236 if(defined $Cache{"get_filename"}{$_[0]}) {
15237 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015238 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015239 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15240 return ($Cache{"get_filename"}{$_[0]}=$1);
15241 }
15242 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015243}
15244
15245sub get_dirname($)
15246{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015247 if(defined $Cache{"get_dirname"}{$_[0]}) {
15248 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015249 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015250 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15251 return ($Cache{"get_dirname"}{$_[0]}=$1);
15252 }
15253 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015254}
15255
15256sub separate_path($) {
15257 return (get_dirname($_[0]), get_filename($_[0]));
15258}
15259
15260sub esc($)
15261{
15262 my $Str = $_[0];
15263 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15264 return $Str;
15265}
15266
15267sub readLineNum($$)
15268{
15269 my ($Path, $Num) = @_;
15270 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015271 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015272 foreach (1 ... $Num) {
15273 <FILE>;
15274 }
15275 my $Line = <FILE>;
15276 close(FILE);
15277 return $Line;
15278}
15279
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015280sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015281{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015282 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015283 return () if(not $Path or not -f $Path);
15284 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015285 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15286 {
15287 foreach my $AttrVal (split(/;/, $1))
15288 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015289 if($AttrVal=~/(.+):(.+)/)
15290 {
15291 my ($Name, $Value) = ($1, $2);
15292 $Attributes{$Name} = $Value;
15293 }
15294 }
15295 }
15296 return \%Attributes;
15297}
15298
15299sub is_abs($) {
15300 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15301}
15302
15303sub get_abs_path($)
15304{ # abs_path() should NOT be called for absolute inputs
15305 # because it can change them
15306 my $Path = $_[0];
15307 if(not is_abs($Path)) {
15308 $Path = abs_path($Path);
15309 }
15310 return $Path;
15311}
15312
15313sub get_OSgroup()
15314{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015315 my $N = $Config{"osname"};
15316 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015317 return "macos";
15318 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015319 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015320 return "bsd";
15321 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015322 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015323 return "beos";
15324 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015325 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015326 return "symbian";
15327 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015328 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015329 return "windows";
15330 }
15331 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015332 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015333 }
15334}
15335
15336sub getGccVersion($)
15337{
15338 my $LibVersion = $_[0];
15339 if($GCC_VERSION{$LibVersion})
15340 { # dump version
15341 return $GCC_VERSION{$LibVersion};
15342 }
15343 elsif($UsedDump{$LibVersion}{"V"})
15344 { # old-version dumps
15345 return "unknown";
15346 }
15347 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15348 if(not $GccVersion) {
15349 return "unknown";
15350 }
15351 return $GccVersion;
15352}
15353
15354sub showArch($)
15355{
15356 my $Arch = $_[0];
15357 if($Arch eq "arm"
15358 or $Arch eq "mips") {
15359 return uc($Arch);
15360 }
15361 return $Arch;
15362}
15363
15364sub getArch($)
15365{
15366 my $LibVersion = $_[0];
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015367
15368 if($TargetArch) {
15369 return $TargetArch;
15370 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015371 elsif($CPU_ARCH{$LibVersion})
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015372 { # dump
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015373 return $CPU_ARCH{$LibVersion};
15374 }
15375 elsif($UsedDump{$LibVersion}{"V"})
15376 { # old-version dumps
15377 return "unknown";
15378 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040015379
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040015380 return getArch_GCC($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015381}
15382
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015383sub get_Report_Title($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015384{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015385 my $Level = $_[0];
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015386
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015387 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015388 if(getArch(1) ne getArch(2)
15389 or getArch(1) eq "unknown"
15390 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015391 { # don't show architecture in the header
15392 $ArchInfo="";
15393 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015394 my $Title = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015395 if($Level eq "Source") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015396 $Title .= "Source compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015397 }
15398 elsif($Level eq "Binary") {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015399 $Title .= "Binary compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015400 }
15401 else {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015402 $Title .= "API compatibility";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015403 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015404
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015405 my $V1 = $Descriptor{1}{"Version"};
15406 my $V2 = $Descriptor{2}{"Version"};
15407
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015408 if($UsedDump{1}{"DWARF"} and $UsedDump{2}{"DWARF"})
15409 {
15410 my $M1 = $UsedDump{1}{"M"};
15411 my $M2 = $UsedDump{2}{"M"};
15412
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015413 my $M1S = $M1;
15414 my $M2S = $M2;
15415
15416 $M1S=~s/(\.so|\.ko)\..+/$1/ig;
15417 $M2S=~s/(\.so|\.ko)\..+/$1/ig;
15418
15419 if($M1S eq $M2S
15420 and $V1 ne "X" and $V2 ne "Y")
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015421 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015422 $Title .= " report for the <span style='color:Blue;'>$M1S</span> $TargetComponent";
15423 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015424 }
15425 else
15426 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015427 $Title .= " report between <span style='color:Blue;'>$M1</span> (<span style='color:Red;'>".$V1."</span>)";
15428 $Title .= " and <span style='color:Blue;'>$M2</span> (<span style='color:Red;'>".$V2."</span>) objects";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015429 }
15430 }
15431 else
15432 {
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030015433 $Title .= " report for the <span style='color:Blue;'>$TargetTitle</span> $TargetComponent";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015434 $Title .= " between <span style='color:Red;'>".$V1."</span> and <span style='color:Red;'>".$V2."</span> versions";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015435 }
15436
15437 $Title .= $ArchInfo;
15438
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015439 if($AppPath) {
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030015440 $Title .= " (relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015441 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015442 $Title = "<h1>".$Title."</h1>\n";
15443 return $Title;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015444}
15445
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015446sub get_CheckedHeaders($)
15447{
15448 my $LibVersion = $_[0];
15449
15450 my @Headers = ();
15451
15452 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
15453 {
15454 my $File = get_filename($Path);
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030015455
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030015456 if(not is_target_header($File, $LibVersion)) {
15457 next;
15458 }
15459
15460 if(skipHeader($File, $LibVersion)) {
15461 next;
15462 }
15463
15464 push(@Headers, $Path);
15465 }
15466
15467 return @Headers;
15468}
15469
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015470sub get_SourceInfo()
15471{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015472 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015473
15474 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015475 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015476 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15477 $CheckedHeaders .= "<div class='h_list'>\n";
15478 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 +040015479 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015480 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15481 my $Name = get_filename($Identity);
15482 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15483 $CheckedHeaders .= $Name.$Comment."<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015484 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015485 $CheckedHeaders .= "</div>\n";
15486 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015487 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015488
15489 if(my @Sources = keys(%{$Registered_Sources{1}}))
15490 {
15491 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15492 $CheckedSources .= "<div class='h_list'>\n";
15493 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15494 {
15495 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15496 my $Name = get_filename($Identity);
15497 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15498 $CheckedSources .= $Name.$Comment."<br/>\n";
15499 }
15500 $CheckedSources .= "</div>\n";
15501 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15502 }
15503
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015504 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015505 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015506 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015507 $CheckedLibs .= "<div class='lib_list'>\n";
15508 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15509 {
15510 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15511 $CheckedLibs .= $Library."<br/>\n";
15512 }
15513 $CheckedLibs .= "</div>\n";
15514 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015515 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015516
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015517 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15518}
15519
15520sub get_ObjTitle()
15521{
15522 if(defined $UsedDump{1}{"DWARF"}) {
15523 return "Objects";
15524 }
15525 else {
15526 return ucfirst($SLIB_TYPE)." Libraries";
15527 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015528}
15529
15530sub get_TypeProblems_Count($$$)
15531{
15532 my ($TypeChanges, $TargetPriority, $Level) = @_;
15533 my $Type_Problems_Count = 0;
15534 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15535 {
15536 my %Kinds_Target = ();
15537 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15538 {
15539 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15540 {
15541 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015542 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
15543 next if($Severity ne $TargetPriority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015544 if($Kinds_Target{$Kind}{$Target}) {
15545 next;
15546 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015547
15548 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target})
15549 {
15550 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
15551 { # select a problem with the highest priority
15552 next;
15553 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015554 }
15555 $Kinds_Target{$Kind}{$Target} = 1;
15556 $Type_Problems_Count += 1;
15557 }
15558 }
15559 }
15560 return $Type_Problems_Count;
15561}
15562
15563sub get_Summary($)
15564{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015565 my $Level = $_[0];
15566 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015567 $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 +040015568 %{$RESULT{$Level}} = (
15569 "Problems"=>0,
15570 "Warnings"=>0,
15571 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015572 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015573 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015574 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015575 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015576 {
15577 if(not defined $CompatRules{$Level}{$Kind})
15578 { # unknown rule
15579 if(not $UnknownRules{$Level}{$Kind})
15580 { # only one warning
15581 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15582 $UnknownRules{$Level}{$Kind}=1;
15583 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015584 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015585 }
15586 }
15587 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015588 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15589 {
15590 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15591 {
15592 if(not defined $CompatRules{$Level}{$Kind})
15593 { # unknown rule
15594 if(not $UnknownRules{$Level}{$Kind})
15595 { # only one warning
15596 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15597 $UnknownRules{$Level}{$Kind}=1;
15598 }
15599 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15600 }
15601 }
15602 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015603 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015604 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015605 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015606 {
15607 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15608 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015609 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015610 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015611 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015612 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015613 $Added += 1;
15614 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015615 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015616 {
15617 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015618 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015619 }
15620 else
15621 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015622 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015623 $I_Other += 1;
15624 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015625 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015626 $I_Problems_High += 1;
15627 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015628 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015629 $I_Problems_Medium += 1;
15630 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015631 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015632 $I_Problems_Low += 1;
15633 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015634 if(($Severity ne "Low" or $StrictCompat)
15635 and $Severity ne "Safe") {
15636 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015637 }
15638 }
15639 }
15640 }
15641 }
15642 }
15643 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015644 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015645 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015646 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015647 {
15648 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15649 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015650 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015651 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015652 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15653 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015654 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015655 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15656
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015657 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015658 { # select a problem with the highest priority
15659 next;
15660 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015661
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015662 if(($Severity ne "Low" or $StrictCompat)
15663 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015664 {
15665 if(defined $TotalAffected{$Level}{$Interface})
15666 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015667 if($Severity_Val{$Severity}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15668 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015669 }
15670 }
15671 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015672 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015673 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015674 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015675
15676 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15677
15678 if($MaxSeverity)
15679 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015680 if($Severity_Val{$Severity}>$Severity_Val{$MaxSeverity}) {
15681 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015682 }
15683 }
15684 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015685 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015686 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015687 }
15688 }
15689 }
15690 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015691
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015692 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15693 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15694 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15695 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015696
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015697 %TypeChanges = (); # free memory
15698
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015699 # changed and removed public symbols
15700 my $SCount = keys(%{$CheckedSymbols{$Level}});
15701 if($ExtendedCheck)
15702 { # don't count external_func_0 for constants
15703 $SCount-=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015704 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015705 if($SCount)
15706 {
15707 my %Weight = (
15708 "High" => 100,
15709 "Medium" => 50,
15710 "Low" => 25
15711 );
15712 foreach (keys(%{$TotalAffected{$Level}})) {
15713 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015714 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015715 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015716 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030015717 else {
15718 $RESULT{$Level}{"Affected"} = 0;
15719 }
15720
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015721 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15722 if($RESULT{$Level}{"Affected"}>=100) {
15723 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015724 }
15725
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015726 $RESULT{$Level}{"Problems"} += $Removed;
15727 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015728 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015729 if($StrictCompat) {
15730 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15731 }
15732 else {
15733 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15734 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015735
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015736 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015737 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015738 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015739 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015740 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015741 if($Severity eq "Safe")
15742 {
15743 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015744 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015745 elsif($Severity eq "Low")
15746 {
15747 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015748 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015749 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015750 }
15751
15752 if($C_Problems_Low)
15753 {
15754 if($StrictCompat) {
15755 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15756 }
15757 else {
15758 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015759 }
15760 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015761 if($RESULT{$Level}{"Problems"}
15762 and $RESULT{$Level}{"Affected"}) {
15763 $RESULT{$Level}{"Verdict"} = "incompatible";
15764 }
15765 else {
15766 $RESULT{$Level}{"Verdict"} = "compatible";
15767 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015768
15769 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15770 if(not $TotalTypes)
15771 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015772 $TotalTypes = keys(%{$TName_Tid{1}});
15773 }
15774
15775 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15776 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15777
15778 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15779
15780 if($ReportFormat eq "xml")
15781 { # XML
15782 # test info
15783 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15784 $TestInfo .= " <version1>\n";
15785 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015786 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015787 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15788 $TestInfo .= " </version1>\n";
15789
15790 $TestInfo .= " <version2>\n";
15791 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015792 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015793 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15794 $TestInfo .= " </version2>\n";
15795 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15796
15797 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015798 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015799 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015800 $TestResults .= " <headers>\n";
15801 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15802 {
15803 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15804 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15805 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15806 }
15807 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015808 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015809
15810 if(my @Sources = keys(%{$Registered_Sources{1}}))
15811 {
15812 $TestResults .= " <sources>\n";
15813 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15814 {
15815 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15816 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15817 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15818 }
15819 $TestResults .= " </sources>\n";
15820 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015821
15822 $TestResults .= " <libs>\n";
15823 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15824 {
15825 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15826 $TestResults .= " <name>$Library</name>\n";
15827 }
15828 $TestResults .= " </libs>\n";
15829
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015830 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015831 $TestResults .= " <types>".$TotalTypes."</types>\n";
15832
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015833 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15834 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015835 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15836
15837 # problem summary
15838 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15839 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15840
15841 $Problem_Summary .= " <problems_with_types>\n";
15842 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15843 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15844 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15845 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15846 $Problem_Summary .= " </problems_with_types>\n";
15847
15848 $Problem_Summary .= " <problems_with_symbols>\n";
15849 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15850 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15851 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015852 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015853 $Problem_Summary .= " </problems_with_symbols>\n";
15854
15855 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015856 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015857 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030015858
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015859 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15860
15861 return ($TestInfo.$TestResults.$Problem_Summary, "");
15862 }
15863 else
15864 { # HTML
15865 # test info
15866 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015867 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030015868
15869 if($TargetComponent eq "library") {
15870 $TestInfo .= "<tr><th>Library Name</th><td>$TargetTitle</td></tr>\n";
15871 }
15872 else {
15873 $TestInfo .= "<tr><th>Module Name</th><td>$TargetTitle</td></tr>\n";
15874 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015875
15876 my (@VInf1, @VInf2, $AddTestInfo) = ();
15877 if($Arch1 ne "unknown"
15878 and $Arch2 ne "unknown")
15879 { # CPU arch
15880 if($Arch1 eq $Arch2)
15881 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015882 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015883 }
15884 else
15885 { # go to the version number
15886 push(@VInf1, showArch($Arch1));
15887 push(@VInf2, showArch($Arch2));
15888 }
15889 }
15890 if($GccV1 ne "unknown"
15891 and $GccV2 ne "unknown"
15892 and $OStarget ne "windows")
15893 { # GCC version
15894 if($GccV1 eq $GccV2)
15895 { # go to the separate section
15896 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15897 }
15898 else
15899 { # go to the version number
15900 push(@VInf1, "gcc ".$GccV1);
15901 push(@VInf2, "gcc ".$GccV2);
15902 }
15903 }
15904 # show long version names with GCC version and CPU architecture name (if different)
15905 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
15906 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
15907 $TestInfo .= $AddTestInfo;
15908 #if($COMMON_LANGUAGE{1}) {
15909 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
15910 #}
15911 if($ExtendedCheck) {
15912 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
15913 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015914 if($JoinReport)
15915 {
15916 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015917 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015918 }
15919 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015920 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015921 }
15922 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015923 $TestInfo .= "</table>\n";
15924
15925 # test results
15926 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015927 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015928
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030015929 if(my @Headers = get_CheckedHeaders(1))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015930 {
15931 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
15932 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
15933 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015934
15935 if(my @Sources = keys(%{$Registered_Sources{1}}))
15936 {
15937 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
15938 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
15939 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015940
15941 if(not $ExtendedCheck)
15942 {
15943 my $Libs_Link = "0";
15944 $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 +040015945 $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 +040015946 }
15947
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015948 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015949
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015950 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015951 if($JoinReport) {
15952 $META_DATA = "kind:".lc($Level).";".$META_DATA;
15953 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015954 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015955 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015956 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
15957 }
15958 else {
15959 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
15960 }
15961 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015962 $TestResults .= "</table>\n";
15963
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015964 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015965 # problem summary
15966 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015967 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015968 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
15969
15970 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015971 if($Added>0)
15972 {
15973 if($JoinReport) {
15974 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
15975 }
15976 else {
15977 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
15978 }
15979 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015980 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015981 $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 +040015982
15983 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015984 if($Removed>0)
15985 {
15986 if($JoinReport) {
15987 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
15988 }
15989 else {
15990 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
15991 }
15992 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015993 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015994 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
15995 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015996
15997 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015998 $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 +040015999 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016000 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
16001 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016002
16003 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016004 $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 +040016005 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016006 $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 +040016007
16008 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016009 $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 +040016010 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016011 $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 +040016012
16013 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016014 $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 +040016015 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016016 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
16017 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016018
16019 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016020 $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 +040016021 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016022 $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 +040016023
16024 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016025 $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 +040016026 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016027 $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 +040016028
16029 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016030 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16031 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016032 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016033 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016034 $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 +040016035
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016036 # Safe Changes
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016037 if($T_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016038 {
16039 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016040 $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 +030016041 $META_DATA .= "type_changes_other:$T_Other;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016042 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016043
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016044 if($I_Other)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016045 {
16046 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016047 $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 +030016048 $META_DATA .= "interface_changes_other:$I_Other;";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016050
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030016051 if($C_Other)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016052 {
16053 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
16054 $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 +030016055 $META_DATA .= "constant_changes_other:$C_Other;";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016056 }
16057
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016058 $META_DATA .= "tool_version:$TOOL_VERSION";
16059 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016060 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016061 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16062 }
16063}
16064
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016065sub getStyle($$$)
16066{
16067 my ($Subj, $Act, $Num) = @_;
16068 my %Style = (
16069 "A"=>"new",
16070 "R"=>"failed",
16071 "S"=>"passed",
16072 "L"=>"warning",
16073 "M"=>"failed",
16074 "H"=>"failed"
16075 );
16076 if($Num>0) {
16077 return " class='".$Style{$Act}."'";
16078 }
16079 return "";
16080}
16081
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016082sub show_number($)
16083{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016084 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016085 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016086 my $Num = cut_off_number($_[0], 2, 0);
16087 if($Num eq "0")
16088 {
16089 foreach my $P (3 .. 7)
16090 {
16091 $Num = cut_off_number($_[0], $P, 1);
16092 if($Num ne "0") {
16093 last;
16094 }
16095 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016096 }
16097 if($Num eq "0") {
16098 $Num = $_[0];
16099 }
16100 return $Num;
16101 }
16102 return $_[0];
16103}
16104
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016105sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016106{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016107 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016108 if($num!~/\./)
16109 {
16110 $num .= ".";
16111 foreach (1 .. $digs_to_cut-1) {
16112 $num .= "0";
16113 }
16114 }
16115 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16116 {
16117 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16118 $num .= "0";
16119 }
16120 }
16121 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16122 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16123 }
16124 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016125 if($z) {
16126 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16127 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016128 return $num;
16129}
16130
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016131sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016132{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016133 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016134 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016135
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016136 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016137 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16138 {
16139 my $Header = $Constants{1}{$Constant}{"Header"};
16140 if(not $Header)
16141 { # added
16142 $Header = $Constants{2}{$Constant}{"Header"}
16143 }
16144
16145 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16146 {
16147 if(not defined $CompatRules{$Level}{$Kind}) {
16148 next;
16149 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016150 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016151 next;
16152 }
16153 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16154 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016155 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016156
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016157 if($ReportFormat eq "xml")
16158 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016159 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016160 {
16161 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016162 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016163 {
16164 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016165 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16166 {
16167 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16168 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16169 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016170
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016171 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16172 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16173 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016174 if($Overcome) {
16175 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16176 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016177 $CHANGED_CONSTANTS .= " </problem>\n";
16178 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016179 $CHANGED_CONSTANTS .= " </constant>\n";
16180 }
16181 $CHANGED_CONSTANTS .= " </header>\n";
16182 }
16183 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16184 }
16185 else
16186 { # HTML
16187 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016188 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016189 {
16190 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016191 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016192 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016193 my $Report = "";
16194
16195 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16196 {
16197 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16198 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016199 $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 +040016200 $Number += 1;
16201 }
16202 if($Report)
16203 {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016204 $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 +040016205 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16206 $Report = insertIDs($Report);
16207 }
16208 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016209 }
16210 $CHANGED_CONSTANTS .= "<br/>\n";
16211 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016212 if($CHANGED_CONSTANTS)
16213 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016214 my $Title = "Problems with Constants, $TargetSeverity Severity";
16215 if($TargetSeverity eq "Safe")
16216 { # Safe Changes
16217 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016218 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016219 $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 +040016220 }
16221 }
16222 return $CHANGED_CONSTANTS;
16223}
16224
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016225sub getTitle($$$)
16226{
16227 my ($Header, $Library, $NameSpace) = @_;
16228 my $Title = "";
16229 if($Library and $Library!~/\.\w+\Z/) {
16230 $Library .= " (.$LIB_EXT)";
16231 }
16232 if($Header and $Library)
16233 {
16234 $Title .= "<span class='h_name'>$Header</span>";
16235 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16236 }
16237 elsif($Library) {
16238 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16239 }
16240 elsif($Header) {
16241 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16242 }
16243 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016244 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016245 }
16246 return $Title;
16247}
16248
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016249sub get_Report_Added($)
16250{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016251 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016252 my $ADDED_INTERFACES = "";
16253 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016254 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016255 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016256 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016257 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016258 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016259 {
16260 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16261 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016262 if($Level eq "Source" and $ReportFormat eq "html")
16263 { # do not show library name in HTML report
16264 $DyLib = "";
16265 }
16266 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016267 }
16268 }
16269 }
16270 if($ReportFormat eq "xml")
16271 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016272 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016273 {
16274 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016275 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016276 {
16277 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016278 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016279 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16280 }
16281 $ADDED_INTERFACES .= " </library>\n";
16282 }
16283 $ADDED_INTERFACES .= " </header>\n";
16284 }
16285 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16286 }
16287 else
16288 { # HTML
16289 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016290 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016291 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016292 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016293 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016294 my %NameSpaceSymbols = ();
16295 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016296 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016297 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016298 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016299 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016300 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16301 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016302 foreach my $Interface (@SortedInterfaces)
16303 {
16304 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016305 my $Signature = get_Signature($Interface, 2);
16306 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016307 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016308 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016309 if($Interface=~/\A(_Z|\?)/)
16310 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016311 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016312 $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 +040016313 }
16314 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016315 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016316 }
16317 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016318 else
16319 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016320 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016321 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016322 }
16323 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016324 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016325 }
16326 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016327 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016328 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016329 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016330 }
16331 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016332 if($ADDED_INTERFACES)
16333 {
16334 my $Anchor = "<a name='Added'></a>";
16335 if($JoinReport) {
16336 $Anchor = "<a name='".$Level."_Added'></a>";
16337 }
16338 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016339 }
16340 }
16341 return $ADDED_INTERFACES;
16342}
16343
16344sub get_Report_Removed($)
16345{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016346 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016347 my $REMOVED_INTERFACES = "";
16348 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016349 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016350 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016351 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016352 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016353 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016354 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016355 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16356 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016357 if($Level eq "Source" and $ReportFormat eq "html")
16358 { # do not show library name in HTML report
16359 $DyLib = "";
16360 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016361 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016362 }
16363 }
16364 }
16365 if($ReportFormat eq "xml")
16366 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016367 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016368 {
16369 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016370 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016371 {
16372 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016373 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16374 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016375 }
16376 $REMOVED_INTERFACES .= " </library>\n";
16377 }
16378 $REMOVED_INTERFACES .= " </header>\n";
16379 }
16380 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16381 }
16382 else
16383 { # HTML
16384 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016385 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016386 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016387 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016388 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016389 my %NameSpaceSymbols = ();
16390 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016391 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016392 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016393 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016394 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016395 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16396 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016397 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016398 {
16399 $Removed_Number += 1;
16400 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016401 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016402 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016403 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016404 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016405 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016406 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016407 if($Signature) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016408 $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 +040016409 }
16410 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016411 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016412 }
16413 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016414 else
16415 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016416 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016417 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016418 }
16419 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016420 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016421 }
16422 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016423 }
16424 }
16425 $REMOVED_INTERFACES .= "<br/>\n";
16426 }
16427 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016428 if($REMOVED_INTERFACES)
16429 {
16430 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16431 if($JoinReport) {
16432 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16433 }
16434 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016435 }
16436 }
16437 return $REMOVED_INTERFACES;
16438}
16439
16440sub getXmlParams($$)
16441{
16442 my ($Content, $Problem) = @_;
16443 return "" if(not $Content or not $Problem);
16444 my %XMLparams = ();
16445 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16446 {
16447 my $Macro = "\@".lc($Attr);
16448 if($Content=~/\Q$Macro\E/) {
16449 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16450 }
16451 }
16452 my @PString = ();
16453 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016454 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016455 }
16456 if(@PString) {
16457 return " ".join(" ", @PString);
16458 }
16459 else {
16460 return "";
16461 }
16462}
16463
16464sub addMarkup($)
16465{
16466 my $Content = $_[0];
16467 # auto-markup
16468 $Content=~s/\n[ ]*//; # spaces
16469 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16470 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016471 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016472 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16473 if($Content=~/\ANOTE:/)
16474 { # notes
16475 $Content=~s!(NOTE):!<b>$1</b>:!g;
16476 }
16477 else {
16478 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16479 }
16480 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16481 my @Keywords = (
16482 "void",
16483 "const",
16484 "static",
16485 "restrict",
16486 "volatile",
16487 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016488 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016489 );
16490 my $MKeys = join("|", @Keywords);
16491 foreach (@Keywords) {
16492 $MKeys .= "|non-".$_;
16493 }
16494 $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 +040016495
16496 # Markdown
16497 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16498 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016499 return $Content;
16500}
16501
16502sub applyMacroses($$$$)
16503{
16504 my ($Level, $Kind, $Content, $Problem) = @_;
16505 return "" if(not $Content or not $Problem);
16506 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16507 $Content = addMarkup($Content);
16508 # macros
16509 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16510 {
16511 my $Macro = "\@".lc($Attr);
16512 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016513 if(not defined $Value
16514 or $Value eq "") {
16515 next;
16516 }
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016517
16518 if(index($Content, $Macro)==-1) {
16519 next;
16520 }
16521
16522 if($Kind!~/\A(Changed|Added|Removed)_Constant\Z/
16523 and $Kind!~/_Type_/
16524 and $Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016525 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016526 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016527 $Value=~s/\s[a-z]\w*(\)|,)/$1/ig; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016528 $Value = black_name($Value);
16529 }
16530 elsif($Value=~/\s/) {
16531 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16532 }
16533 elsif($Value=~/\A\d+\Z/
16534 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16535 { # bits to bytes
16536 if($Value % $BYTE_SIZE)
16537 { # bits
16538 if($Value==1) {
16539 $Value = "<b>".$Value."</b> bit";
16540 }
16541 else {
16542 $Value = "<b>".$Value."</b> bits";
16543 }
16544 }
16545 else
16546 { # bytes
16547 $Value /= $BYTE_SIZE;
16548 if($Value==1) {
16549 $Value = "<b>".$Value."</b> byte";
16550 }
16551 else {
16552 $Value = "<b>".$Value."</b> bytes";
16553 }
16554 }
16555 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016556 else
16557 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016558 $Value = "<b>".htmlSpecChars($Value)."</b>";
16559 }
16560 $Content=~s/\Q$Macro\E/$Value/g;
16561 }
16562
16563 if($Content=~/(\A|[^\@\w])\@\w/)
16564 {
16565 if(not $IncompleteRules{$Level}{$Kind})
16566 { # only one warning
16567 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16568 $IncompleteRules{$Level}{$Kind} = 1;
16569 }
16570 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016571 return $Content;
16572}
16573
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016574sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016575{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016576 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016577 my $INTERFACE_PROBLEMS = "";
16578 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016579
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016580 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016581 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016582 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16583 if($SV and defined $CompatProblems{$Level}{$SN}) {
16584 next;
16585 }
16586 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016587 {
16588 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016589 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016590 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016591 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16592 my $DyLib = $Symbol_Library{1}{$Symbol};
16593 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016594 { # Symbol with Version
16595 $DyLib = $Symbol_Library{1}{$VSym};
16596 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016597 if(not $DyLib)
16598 { # const global data
16599 $DyLib = "";
16600 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016601 if($Level eq "Source" and $ReportFormat eq "html")
16602 { # do not show library name in HTML report
16603 $DyLib = "";
16604 }
16605 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16606 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016607 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016608 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16609 if($Severity ne $TargetSeverity) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016610 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016611 }
16612 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016613 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16614 {
16615 delete($SymbolChanges{$Symbol}{$Kind});
16616 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016617 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016618 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016619 }
16620 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016621 if(not keys(%{$SymbolChanges{$Symbol}})) {
16622 delete($SymbolChanges{$Symbol});
16623 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016624 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016625
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016626 if($ReportFormat eq "xml")
16627 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016628 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016629 {
16630 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016631 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016632 {
16633 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016634 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16635 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016636 {
16637 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16638 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16639 {
16640 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16641 {
16642 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016643 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016644
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016645 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16646 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16647 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16648 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16649 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016650 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16651 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16652 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016653 $INTERFACE_PROBLEMS .= " </problem>\n";
16654 }
16655 }
16656 $INTERFACE_PROBLEMS .= " </symbol>\n";
16657 }
16658 $INTERFACE_PROBLEMS .= " </library>\n";
16659 }
16660 $INTERFACE_PROBLEMS .= " </header>\n";
16661 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016662 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016663 }
16664 else
16665 { # HTML
16666 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016667 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016668 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016669 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016670 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016671 my (%NameSpaceSymbols, %NewSignature) = ();
16672 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016673 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016674 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016675 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016676 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016677 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016678 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 +040016679 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016680 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016681 my $Signature = get_Signature($Symbol, 1);
16682 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016683 my $ProblemNum = 1;
Andrey Ponomarenko28874762015-08-28 21:59:28 +030016684 foreach my $Kind (sort keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016685 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016686 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016687 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016688 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016689 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016690 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016691 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016692 }
16693 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16694 {
16695 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016696 $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 +040016697 $ProblemNum += 1;
16698 $ProblemsNum += 1;
16699 }
16700 }
16701 }
16702 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016703 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016704 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016705 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016706 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016707 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016708 }
16709 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016710 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016711 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016712 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16713 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16714 if($NewSignature{$Symbol})
16715 { # argument list changed to
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016716 $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 +040016717 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016718 if($Symbol=~/\A(_Z|\?)/) {
16719 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16720 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016721 $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 +040016722 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016723 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016724 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016725 }
16726 }
16727 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016728 $INTERFACE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016729 }
16730 }
16731 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016732
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016733 if($INTERFACE_PROBLEMS)
16734 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016735 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16736 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16737 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016738 { # Safe Changes
16739 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016740 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016741 $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 +040016742 }
16743 }
16744 return $INTERFACE_PROBLEMS;
16745}
16746
16747sub get_Report_TypeProblems($$)
16748{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016749 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016750 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016751 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016752
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016753 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016754 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016755 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016756 {
16757 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16758 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016759 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016760 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016761 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016762 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016763 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016764
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016765 if($Severity eq "Safe"
16766 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016767 next;
16768 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016769
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016770 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target})
16771 {
16772 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
16773 { # select a problem with the highest priority
16774 next;
16775 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016776 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016777
16778 $TypeChanges{$TypeName}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016779 }
16780 }
16781 }
16782 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016783
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016784 my %Kinds_Locations = ();
16785 foreach my $TypeName (keys(%TypeChanges))
16786 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016787 my %Kind_Target = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016788 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16789 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016790 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016791 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016792 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016793 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016794 { # other priority
16795 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16796 next;
16797 }
16798 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16799 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016800 if($Kind_Target{$Kind}{$Target})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016801 { # duplicate target
16802 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16803 next;
16804 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016805 $Kind_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016806 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016807 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016808 }
16809 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16810 delete($TypeChanges{$TypeName}{$Kind});
16811 }
16812 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016813 if(not keys(%{$TypeChanges{$TypeName}})) {
16814 delete($TypeChanges{$TypeName});
16815 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016816 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016817
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016818 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 +040016819 if($ReportFormat eq "xml")
16820 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016821 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016822 {
16823 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016824 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016825 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016826 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016827 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16828 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016829 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016830 {
16831 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16832 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16833 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16834 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16835 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16836 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016837 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16838 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16839 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016840 $TYPE_PROBLEMS .= " </problem>\n";
16841 }
16842 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016843 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016844 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016845 $TYPE_PROBLEMS .= showVTables($TypeName);
16846 }
16847 $TYPE_PROBLEMS .= " </type>\n";
16848 }
16849 $TYPE_PROBLEMS .= " </header>\n";
16850 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016851 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016852 }
16853 else
16854 { # HTML
16855 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016856 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016857 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016858 my (%NameSpace_Type) = ();
16859 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016860 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016861 }
16862 foreach my $NameSpace (sort keys(%NameSpace_Type))
16863 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016864 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016865 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 +040016866 foreach my $TypeName (@SortedTypes)
16867 {
16868 my $ProblemNum = 1;
16869 my $TYPE_REPORT = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016870
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016871 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16872 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016873 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016874 {
16875 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16876 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16877 {
16878 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016879 $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 +040016880 $ProblemNum += 1;
16881 $ProblemsNum += 1;
16882 }
16883 }
16884 }
16885 $ProblemNum -= 1;
16886 if($TYPE_REPORT)
16887 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016888 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016889 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016890 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016891 $ShowVTables = showVTables($TypeName);
16892 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016893
16894 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016895 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
16896 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
16897 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
16898 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016899 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016900 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016901 }
16902 }
16903 }
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030016904 $TYPE_PROBLEMS .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016905 }
16906 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016907
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016908 if($TYPE_PROBLEMS)
16909 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016910 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
16911 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016912 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016913 { # Safe Changes
16914 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016915 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016916 $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 +040016917 }
16918 }
16919 return $TYPE_PROBLEMS;
16920}
16921
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016922sub show_Type($$$)
16923{
16924 my ($Name, $Html, $LibVersion) = @_;
16925 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
16926 $TType = lc($TType);
16927 if($TType=~/struct|union|enum/) {
16928 $Name=~s/\A\Q$TType\E //g;
16929 }
16930 if($Html) {
16931 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
16932 }
16933 else {
16934 $Name = $TType." ".$Name;
16935 }
16936 return $Name;
16937}
16938
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016939sub get_Anchor($$$)
16940{
16941 my ($Kind, $Level, $Severity) = @_;
16942 if($JoinReport)
16943 {
16944 if($Severity eq "Safe") {
16945 return "Other_".$Level."_Changes_In_".$Kind."s";
16946 }
16947 else {
16948 return $Kind."_".$Level."_Problems_".$Severity;
16949 }
16950 }
16951 else
16952 {
16953 if($Severity eq "Safe") {
16954 return "Other_Changes_In_".$Kind."s";
16955 }
16956 else {
16957 return $Kind."_Problems_".$Severity;
16958 }
16959 }
16960}
16961
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016962sub showVTables($)
16963{
16964 my $TypeName = $_[0];
16965 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016966 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016967 if(defined $Type1{"VTable"}
16968 and keys(%{$Type1{"VTable"}}))
16969 {
16970 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016971 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016972 if(defined $Type2{"VTable"}
16973 and keys(%{$Type2{"VTable"}}))
16974 {
16975 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
16976 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016977 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016978 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016979 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
16980 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016981 }
16982 my $VTABLES = "";
16983 if($ReportFormat eq "xml")
16984 { # XML
16985 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016986 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016987 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016988 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016989 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
16990 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016991 $VTABLES .= " </entry>\n";
16992 }
16993 $VTABLES .= " </vtable>\n\n";
16994 }
16995 else
16996 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016997 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030016998 $VTABLES .= "<tr><th>Offset</th>";
16999 $VTABLES .= "<th>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017000 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017001 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017002 {
17003 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017004 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017005 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017006 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017007 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017008 $Color1 = " class='failed'";
17009 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017010 }
17011 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017012 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017013 }
17014 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017015 $VTABLES .= "<tr><th>".$Index."</th>\n";
17016 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17017 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017018 }
17019 $VTABLES .= "</table><br/>\n";
17020 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017021 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017022 }
17023 return $VTABLES;
17024 }
17025 }
17026 return "";
17027}
17028
17029sub simpleVEntry($)
17030{
17031 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017032 if(not defined $VEntry
17033 or $VEntry eq "") {
17034 return "";
17035 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017036
17037 $VEntry=~s/ \[.+?\]\Z//; # support for ABI Dumper
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017038 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17039 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17040 if($VEntry=~/\A_ZThn.+\Z/) {
17041 $VEntry = "non-virtual thunk";
17042 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017043 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017044 # support for old GCC versions
17045 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17046 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17047 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017048 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17049 return $VEntry;
17050}
17051
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017052sub adjustParamPos($$$)
17053{
17054 my ($Pos, $Symbol, $LibVersion) = @_;
17055 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17056 {
17057 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17058 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17059 {
17060 return $Pos-1;
17061 }
17062
17063 return $Pos;
17064 }
17065
17066 return undef;
17067}
17068
17069sub getParamPos($$$)
17070{
17071 my ($Name, $Symbol, $LibVersion) = @_;
17072
17073 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17074 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17075 {
17076 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17077 foreach (keys(%{$Info->{"Param"}}))
17078 {
17079 if($Info->{"Param"}{$_}{"name"} eq $Name)
17080 {
17081 return $_;
17082 }
17083 }
17084 }
17085
17086 return undef;
17087}
17088
17089sub getParamName($)
17090{
17091 my $Loc = $_[0];
17092 $Loc=~s/\->.*//g;
17093 return $Loc;
17094}
17095
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017096sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017097{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017098 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017099 my $LIMIT = 10;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017100
17101 if(defined $AffectLimit)
17102 {
17103 $LIMIT = $AffectLimit;
17104 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017105
17106 my %SymSel = ();
17107 my %SymLocKind = ();
17108
17109 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017110 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017111 if(index($Symbol, "_Z")==0
17112 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017113 { # duplicated problems for C2 constructors, D2 and D0 destructors
17114 next;
17115 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017116
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017117 foreach my $Kind (sort keys(%{$Kinds_Locations}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017118 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017119 if(not defined $CompatProblems{$Level}{$Symbol}
17120 or not defined $CompatProblems{$Level}{$Symbol}{$Kind}) {
17121 next;
17122 }
17123
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017124 foreach my $Loc (sort keys(%{$Kinds_Locations->{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017125 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017126 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017127 next;
17128 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017129
17130 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17131 if($Level eq "Source")
17132 { # remove symbol version
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017133 $Symbol = $SN;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017134 }
17135
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017136 if($SV and defined $CompatProblems{$Level}{$SN}
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017137 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Loc})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017138 { # duplicated problems for versioned symbols
17139 next;
17140 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017141
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017142 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Loc}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017143 if($Type_Name ne $Target_TypeName) {
17144 next;
17145 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017146
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017147 $SymLocKind{$Symbol}{$Loc}{$Kind} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017148 }
17149 }
17150 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017151
17152 foreach my $Symbol (sort keys(%SymLocKind))
17153 {
17154 LOOP: foreach my $Loc (sort {$a=~/retval/ cmp $b=~/retval/} sort {length($a)<=>length($b)} sort keys(%{$SymLocKind{$Symbol}}))
17155 {
17156 foreach my $Kind (keys(%{$SymLocKind{$Symbol}{$Loc}}))
17157 {
17158 $SymSel{$Symbol}{"Loc"} = $Loc;
17159 $SymSel{$Symbol}{"Kind"} = $Kind;
17160
17161 last LOOP;
17162 }
17163 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017164 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017165
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017166 my $Affected = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017167 my $Num = 0;
17168
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017169 if($ReportFormat eq "xml")
17170 { # XML
17171 $Affected .= " <affected>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017172
17173 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017174 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017175 my $Loc = $SymSel{$Symbol}{"Loc"};
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017176 my $PName = getParamName($Loc);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030017177 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $Loc);
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017178
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017179 my $Target = "";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017180 if($PName)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017181 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017182 $Target .= " param=\"$PName\"";
17183 $Desc=~s/parameter $PName /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017184 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017185 elsif($Loc=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017186 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017187 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017188 elsif($Loc=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017189 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017190 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017191
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017192 if($Desc=~s/\AField ([^\s]+) /Field \@field /) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017193 $Target .= " field=\"$1\"";
17194 }
17195
17196 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017197 $Affected .= " <comment>".xmlSpecChars($Desc)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017198 $Affected .= " </symbol>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017199
17200 if($Num>$LIMIT) {
17201 last LOOP;
17202 }
17203
17204 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017205 }
17206 $Affected .= " </affected>\n";
17207 }
17208 else
17209 { # HTML
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017210 foreach my $Symbol (sort {lc($a) cmp lc($b)} keys(%SymSel))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017211 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017212 my $Desc = getAffectDesc($Level, $Symbol, $SymSel{$Symbol}{"Kind"}, $SymSel{$Symbol}{"Loc"});
17213 my $S = get_Signature($Symbol, 1);
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017214 my $PName = getParamName($SymSel{$Symbol}{"Loc"});
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017215 my $Pos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17216
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017217 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($S, $Pos, 1, 0, 0)."</span><br/>\n";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017218 $Affected .= "<div class='affect'>".htmlSpecChars($Desc)."</div>\n";
17219
17220 if($Num>$LIMIT) {
17221 last;
17222 }
17223
17224 $Num += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017225 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017226
17227 if(keys(%SymSel)>$LIMIT) {
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017228 $Affected .= " ...\n<br/>\n"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017229 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017230
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017231 $Affected = "<div class='affected'>".$Affected."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017232 if($Affected)
17233 {
17234 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017235 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".keys(%SymSel).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017236 }
17237 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017238
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017239 return $Affected;
17240}
17241
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017242sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017243{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017244 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017245 if($L2=~/\A(retval|this)\b/
17246 and $L1!~/\A(retval|this)\b/)
17247 {
17248 if($L1!~/\-\>/) {
17249 return 1;
17250 }
17251 elsif($L2=~/\-\>/) {
17252 return 1;
17253 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017254 }
17255 return 0;
17256}
17257
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017258sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017259{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017260 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017261
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017262 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017263
17264 my $Location_I = $Location;
17265 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17266
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017267 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017268
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017269 if($Kind eq "Overridden_Virtual_Method"
17270 or $Kind eq "Overridden_Virtual_Method_B") {
17271 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17272 }
17273 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17274 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017275 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17276
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017277 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17278 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017279 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17280 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17281
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017282 if($ClassName eq $Problem{"Type_Name"}) {
17283 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17284 }
17285 else {
17286 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17287 }
17288 }
17289 else
17290 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017291 my $TypeID = undef;
17292
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017293 if($Location=~/retval/)
17294 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017295 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017296 push(@Sentence, "Field \'".$Location."\' in return value");
17297 }
17298 else {
17299 push(@Sentence, "Return value");
17300 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017301
17302 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017303 }
17304 elsif($Location=~/this/)
17305 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017306 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017307 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17308 }
17309 else {
17310 push(@Sentence, "\'this\' pointer");
17311 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017312
17313 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017314 }
17315 else
17316 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017317
17318 my $PName = getParamName($Location);
17319 my $PPos = getParamPos($PName, $Symbol, 1);
17320
17321 if(index($Location, "->")!=-1) {
17322 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017323 }
17324 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017325 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017326 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017327 if($PName) {
17328 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017329 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017330
17331 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17332 }
17333
17334 if($Location!~/this/)
17335 {
17336 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017337 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017338 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017339 push(@Sentence, "(pointer)");
17340 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017341 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017342 push(@Sentence, "(reference)");
17343 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017344 }
17345 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017346
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017347 if($Location eq "this") {
17348 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17349 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017350 else
17351 {
17352 my $Location_T = $Location;
17353 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17354
17355 my $TypeID_Problem = $TypeID;
17356 if($Location_T) {
17357 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17358 }
17359
17360 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17361 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17362 }
17363 else {
17364 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17365 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017366 }
17367 }
17368 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017369 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017370 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 +040017371 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017372
17373 my $Sent = join(" ", @Sentence);
17374
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017375 $Sent=~s/->/./g;
17376
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017377 if($ReportFormat eq "xml")
17378 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017379 $Sent=~s/'//g;
17380 }
17381
17382 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017383}
17384
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017385sub getFieldType($$$)
17386{
17387 my ($Location, $TypeId, $LibVersion) = @_;
17388
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017389 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017390
17391 foreach my $Name (@Fields)
17392 {
17393 my %Info = get_BaseType($TypeId, $LibVersion);
17394
17395 foreach my $Pos (keys(%{$Info{"Memb"}}))
17396 {
17397 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17398 {
17399 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17400 last;
17401 }
17402 }
17403 }
17404
17405 return $TypeId;
17406}
17407
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017408sub get_XmlSign($$)
17409{
17410 my ($Symbol, $LibVersion) = @_;
17411 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17412 my $Report = "";
17413 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17414 {
17415 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017416 my $Type = $Info->{"Param"}{$Pos}{"type"};
17417 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017418 foreach my $Typedef (keys(%ChangedTypedef))
17419 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017420 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17421 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17422 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017423 }
17424 $Report .= " <param pos=\"$Pos\">\n";
17425 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017426 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017427 $Report .= " </param>\n";
17428 }
17429 if(my $Return = $Info->{"Return"})
17430 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017431 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017432 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017433 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017434 $Report .= " </retval>\n";
17435 }
17436 return $Report;
17437}
17438
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017439sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017440{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017441 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017442 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017443 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017444 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017445 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17446 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017447 next;
17448 }
17449 $Report .= " <symbol name=\"$Symbol\">\n";
17450 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017451 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017452 {
17453 if(defined $CompleteSignature{1}{$Symbol}
17454 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17455 {
17456 $P1 = get_XmlSign($Symbol, 1);
17457 $S1 = get_Signature($Symbol, 1);
17458 }
17459 elsif($Symbol=~/\A(_Z|\?)/) {
17460 $S1 = $tr_name{$Symbol};
17461 }
17462 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017463 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017464 {
17465 if(defined $CompleteSignature{2}{$Symbol}
17466 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17467 {
17468 $P2 = get_XmlSign($Symbol, 2);
17469 $S2 = get_Signature($Symbol, 2);
17470 }
17471 elsif($Symbol=~/\A(_Z|\?)/) {
17472 $S2 = $tr_name{$Symbol};
17473 }
17474 }
17475 if($S1)
17476 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017477 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017478 $Report .= $P1;
17479 $Report .= " </old>\n";
17480 }
17481 if($S2 and $S2 ne $S1)
17482 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017483 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017484 $Report .= $P2;
17485 $Report .= " </new>\n";
17486 }
17487 $Report .= " </symbol>\n";
17488 }
17489 $Report .= "</symbols_info>\n";
17490 return $Report;
17491}
17492
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017493sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017494{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017495 my ($Level, $Report) = @_;
17496 if($ReportFormat eq "xml") {
17497 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017498 }
17499 if($StdOut)
17500 { # --stdout option
17501 print STDOUT $Report;
17502 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017503 else
17504 {
17505 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017506 mkpath(get_dirname($RPath));
17507
17508 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17509 print REPORT $Report;
17510 close(REPORT);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017511 }
17512}
17513
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017514sub getReport($)
17515{
17516 my $Level = $_[0];
17517 if($ReportFormat eq "xml")
17518 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017519 if($Level eq "Join")
17520 {
17521 my $Report = "<reports>\n";
17522 $Report .= getReport("Binary");
17523 $Report .= getReport("Source");
17524 $Report .= "</reports>\n";
17525 return $Report;
17526 }
17527 else
17528 {
17529 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17530 my ($Summary, $MetaData) = get_Summary($Level);
17531 $Report .= $Summary."\n";
17532 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17533 $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 +040017534
17535 # additional symbols info (if needed)
17536 # $Report .= get_Report_SymbolsInfo($Level);
17537
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017538 $Report .= "</report>\n";
17539 return $Report;
17540 }
17541 }
17542 else
17543 { # HTML
17544 my $CssStyles = readModule("Styles", "Report.css");
17545 my $JScripts = readModule("Scripts", "Sections.js");
17546 if($Level eq "Join")
17547 {
17548 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17549 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017550 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017551 my $Keywords = $TargetTitle.", compatibility, API, ABI, report";
17552 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 +040017553 my ($BSummary, $BMetaData) = get_Summary("Binary");
17554 my ($SSummary, $SMetaData) = get_Summary("Source");
17555 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 +030017556 $Report .= get_Report_Title("Join")."
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030017557 <br/>
17558 <div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017559 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17560 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017561 </div>";
17562 $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>";
17563 $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 +030017564 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017565 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017566 return $Report;
17567 }
17568 else
17569 {
17570 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030017571 my $Title = $TargetTitle.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17572 my $Keywords = $TargetTitle.", ".lc($Level)." compatibility, API, report";
17573 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 +040017574 if($Level eq "Binary")
17575 {
17576 if(getArch(1) eq getArch(2)
17577 and getArch(1) ne "unknown") {
17578 $Description .= " on ".showArch(getArch(1));
17579 }
17580 }
17581 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 +030017582 $Report .= get_Report_Title($Level)."\n".$Summary."\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017583 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17584 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17585 $Report .= get_SourceInfo();
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017586 $Report .= "</div>\n<br/><br/><br/>\n";
17587 $Report .= getReportFooter();
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017588 $Report .= "\n</body></html>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017589 return $Report;
17590 }
17591 }
17592}
17593
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017594sub getLegend()
17595{
17596 return "<br/>
17597<table class='summary'>
17598<tr>
17599 <td class='new'>added</td>
17600 <td class='passed'>compatible</td>
17601</tr>
17602<tr>
17603 <td class='warning'>warning</td>
17604 <td class='failed'>incompatible</td>
17605</tr></table>\n";
17606}
17607
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017608sub createReport()
17609{
17610 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017611 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017612 writeReport("Join", getReport("Join"));
17613 }
17614 elsif($DoubleReport)
17615 { # default
17616 writeReport("Binary", getReport("Binary"));
17617 writeReport("Source", getReport("Source"));
17618 }
17619 elsif($BinaryOnly)
17620 { # --binary
17621 writeReport("Binary", getReport("Binary"));
17622 }
17623 elsif($SourceOnly)
17624 { # --source
17625 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017626 }
17627}
17628
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017629sub getReportFooter()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017630{
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017631 my $Footer = "";
Andrey Ponomarenko01e8e502015-08-21 22:08:40 +030017632
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017633 $Footer .= "<hr/>";
17634 $Footer .= "<div class='footer' align='right'><i>Generated on ".localtime(time);
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030017635 $Footer .= " by <a href='".$HomePage."'>ABI Compliance Checker</a> $TOOL_VERSION &#160;";
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017636 $Footer .= "</i></div>";
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030017637 $Footer .= "<br/>\n";
17638
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017639 return $Footer;
17640}
17641
17642sub get_Report_Problems($$)
17643{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017644 my ($Severity, $Level) = @_;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017645
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017646 my $Report = get_Report_TypeProblems($Severity, $Level);
17647 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017648 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017649 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017650
17651 if($Severity eq "Low" or $Severity eq "Safe") {
17652 $Report .= get_Report_ChangedConstants($Severity, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017653 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030017654
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017655 if($ReportFormat eq "html")
17656 {
17657 if($Report)
17658 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017659 if($JoinReport)
17660 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017661 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017662 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17663 }
17664 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017665 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017666 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017667 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017668 else
17669 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017670 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017671 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17672 }
17673 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017674 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017675 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017676 }
17677 }
17678 }
17679 return $Report;
17680}
17681
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017682sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017683{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017684 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17685 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17686 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17687 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017688 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17689 <meta name=\"keywords\" content=\"$Keywords\" />
17690 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017691 <title>
17692 $Title
17693 </title>
17694 <style type=\"text/css\">
17695 $Styles
17696 </style>
17697 <script type=\"text/javascript\" language=\"JavaScript\">
17698 <!--
17699 $Scripts
17700 -->
17701 </script>
17702 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017703}
17704
17705sub insertIDs($)
17706{
17707 my $Text = $_[0];
17708 while($Text=~/CONTENT_ID/)
17709 {
17710 if(int($Content_Counter)%2) {
17711 $ContentID -= 1;
17712 }
17713 $Text=~s/CONTENT_ID/c_$ContentID/;
17714 $ContentID += 1;
17715 $Content_Counter += 1;
17716 }
17717 return $Text;
17718}
17719
17720sub checkPreprocessedUnit($)
17721{
17722 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017723 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017724 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017725 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017726
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017727 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017728 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017729 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017730 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017731 chomp($Line);
17732 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017733 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017734 $CurHeader = path_format($1, $OSgroup);
17735 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017736 $CurClass = "";
17737
17738 if(index($CurHeader, $TMP_DIR)==0) {
17739 next;
17740 }
17741
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017742 if(substr($CurHeaderName, 0, 1) eq "<")
17743 { # <built-in>, <command-line>, etc.
17744 $CurHeaderName = "";
17745 $CurHeader = "";
17746 }
17747
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017748 if($ExtraInfo)
17749 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017750 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017751 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17752 }
17753 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017754 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017755 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017756 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017757 if($CurHeaderName)
17758 {
17759 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17760 and not $Registered_Headers{$Version}{$CurHeader})
17761 { # not a target
17762 next;
17763 }
17764 if(not is_target_header($CurHeaderName, 1)
17765 and not is_target_header($CurHeaderName, 2))
17766 { # user-defined header
17767 next;
17768 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017769 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017770 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017771
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017772 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017773 {
17774 my ($Name, $Value) = ($1, $2);
17775 if(not $Constants{$Version}{$Name}{"Access"})
17776 {
17777 $Constants{$Version}{$Name}{"Access"} = "public";
17778 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017779 if($CurHeaderName) {
17780 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17781 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017782 }
17783 }
17784 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17785 $Constants{$Version}{$1}{"Access"} = "private";
17786 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017787 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017788 else
17789 {
17790 if(defined $ExtraDump)
17791 {
17792 if($Line=~/(\w+)\s*\(/)
17793 { # functions
17794 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17795 }
17796 #elsif($Line=~/(\w+)\s*;/)
17797 #{ # data
17798 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17799 #}
17800 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17801 $CurClass = $2;
17802 }
17803 }
17804 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017805 }
17806 close(PREPROC);
17807 foreach my $Constant (keys(%{$Constants{$Version}}))
17808 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017809 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17810 {
17811 delete($Constants{$Version}{$Constant});
17812 next;
17813 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017814 if(not $ExtraDump and ($Constant=~/_h\Z/i
17815 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017816 { # skip
17817 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017818 }
17819 else {
17820 delete($Constants{$Version}{$Constant}{"Access"});
17821 }
17822 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017823 if($Debug)
17824 {
17825 mkpath($DEBUG_PATH{$Version});
17826 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17827 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017828}
17829
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017830sub uncoverConstant($$)
17831{
17832 my ($LibVersion, $Constant) = @_;
17833 return "" if(not $LibVersion or not $Constant);
17834 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17835 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17836 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17837 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017838
17839 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017840 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017841 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17842 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017843 {
17844 push(@RecurConstant, $Constant);
17845 my $Uncovered = uncoverConstant($LibVersion, $Value);
17846 if($Uncovered ne "") {
17847 $Value = $Uncovered;
17848 }
17849 pop(@RecurConstant);
17850 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017851
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017852 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017853 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017854 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17855 }
17856 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17857}
17858
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017859sub simpleConstant($$)
17860{
17861 my ($LibVersion, $Value) = @_;
17862 if($Value=~/\W/)
17863 {
17864 my $Value_Copy = $Value;
17865 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
17866 {
17867 my $Word = $1;
17868 if($Value!~/$Word\s*\(/)
17869 {
17870 my $Val = uncoverConstant($LibVersion, $Word);
17871 if($Val ne "")
17872 {
17873 $Value=~s/\b$Word\b/$Val/g;
17874 }
17875 }
17876 }
17877 }
17878 return $Value;
17879}
17880
17881sub computeValue($)
17882{
17883 my $Value = $_[0];
17884
17885 if($Value=~/\A\((-?[\d]+)\)\Z/) {
17886 return $1;
17887 }
17888
17889 if($Value=~/\A[\d\-\+()]+\Z/) {
17890 return eval($Value);
17891 }
17892
17893 return $Value;
17894}
17895
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017896my %IgnoreConstant = map {$_=>1} (
17897 "VERSION",
17898 "VERSIONCODE",
17899 "VERNUM",
17900 "VERS_INFO",
17901 "PATCHLEVEL",
17902 "INSTALLPREFIX",
17903 "VBUILD",
17904 "VPATCH",
17905 "VMINOR",
17906 "BUILD_STRING",
17907 "BUILD_TIME",
17908 "PACKAGE_STRING",
17909 "PRODUCTION",
17910 "CONFIGURE_COMMAND",
17911 "INSTALLDIR",
17912 "BINDIR",
17913 "CONFIG_FILE_PATH",
17914 "DATADIR",
17915 "EXTENSION_DIR",
17916 "INCLUDE_PATH",
17917 "LIBDIR",
17918 "LOCALSTATEDIR",
17919 "SBINDIR",
17920 "SYSCONFDIR",
17921 "RELEASE",
17922 "SOURCE_ID",
17923 "SUBMINOR",
17924 "MINOR",
17925 "MINNOR",
17926 "MINORVERSION",
17927 "MAJOR",
17928 "MAJORVERSION",
17929 "MICRO",
17930 "MICROVERSION",
17931 "BINARY_AGE",
17932 "INTERFACE_AGE",
17933 "CORE_ABI",
17934 "PATCH",
17935 "COPYRIGHT",
17936 "TIMESTAMP",
17937 "REVISION",
17938 "PACKAGE_TAG",
17939 "PACKAGEDATE",
17940 "NUMVERSION",
17941 "Release",
17942 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017943);
17944
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017945sub constantFilter($$$)
17946{
17947 my ($Name, $Value, $Level) = @_;
17948
17949 if($Level eq "Binary")
17950 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017951 if($Name=~/_t\Z/)
17952 { # __malloc_ptr_t
17953 return 1;
17954 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017955 foreach (keys(%IgnoreConstant))
17956 {
17957 if($Name=~/(\A|_)$_(_|\Z)/)
17958 { # version
17959 return 1;
17960 }
17961 if(/\A[A-Z].*[a-z]\Z/)
17962 {
17963 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
17964 { # version
17965 return 1;
17966 }
17967 }
17968 }
17969 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
17970 { # version
17971 return 1;
17972 }
17973 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
17974 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
17975 return 1;
17976 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017977
17978 if($Value=~/\A["'].*['"]/i)
17979 { # string
17980 return 0;
17981 }
17982
17983 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
17984 { # static int gcry_pth_init
17985 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017986 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017987 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017988 return 1;
17989 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017990 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017991 { # foo(p)
17992 return 1;
17993 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017994 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017995 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017996 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017997 return 1;
17998 }
17999 }
18000
18001 return 0;
18002}
18003
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018004sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018005{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018006 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018007 foreach my $Constant (keys(%{$Constants{1}}))
18008 {
18009 if($SkipConstants{1}{$Constant})
18010 { # skipped by the user
18011 next;
18012 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018013
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018014 if(my $Header = $Constants{1}{$Constant}{"Header"})
18015 {
18016 if(not is_target_header($Header, 1)
18017 and not is_target_header($Header, 2))
18018 { # user-defined header
18019 next;
18020 }
18021 }
18022 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018023 next;
18024 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018025
18026 my $Old_Value = uncoverConstant(1, $Constant);
18027
18028 if(constantFilter($Constant, $Old_Value, $Level))
18029 { # separate binary and source problems
18030 next;
18031 }
18032
18033 if(not defined $Constants{2}{$Constant}{"Value"})
18034 { # removed
18035 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18036 "Target"=>$Constant,
18037 "Old_Value"=>$Old_Value );
18038 next;
18039 }
18040
18041 if($Constants{2}{$Constant}{"Value"} eq "")
18042 { # empty value
18043 # TODO: implement a rule
18044 next;
18045 }
18046
18047 my $New_Value = uncoverConstant(2, $Constant);
18048
18049 my $Old_Value_Pure = $Old_Value;
18050 my $New_Value_Pure = $New_Value;
18051
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018052 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18053 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18054 $New_Value_Pure=~s/(\W)\s+/$1/g;
18055 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018056
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018057 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018058
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018059 if($New_Value_Pure ne $Old_Value_Pure)
18060 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018061 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18062 { # complex values
18063 next;
18064 }
18065 if(computeValue($Old_Value) eq computeValue($New_Value))
18066 { # expressions
18067 next;
18068 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018069 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18070 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18071 next;
18072 }
18073 if($Old_Value eq "0" and $New_Value eq "NULL")
18074 { # 0 => NULL
18075 next;
18076 }
18077 if($Old_Value eq "NULL" and $New_Value eq "0")
18078 { # NULL => 0
18079 next;
18080 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018081 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018082 "Target"=>$Constant,
18083 "Old_Value"=>$Old_Value,
18084 "New_Value"=>$New_Value );
18085 }
18086 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018087
18088 foreach my $Constant (keys(%{$Constants{2}}))
18089 {
18090 if(not defined $Constants{1}{$Constant}{"Value"})
18091 {
18092 if($SkipConstants{2}{$Constant})
18093 { # skipped by the user
18094 next;
18095 }
18096
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018097 if(my $Header = $Constants{2}{$Constant}{"Header"})
18098 {
18099 if(not is_target_header($Header, 1)
18100 and not is_target_header($Header, 2))
18101 { # user-defined header
18102 next;
18103 }
18104 }
18105 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018106 next;
18107 }
18108
18109 my $New_Value = uncoverConstant(2, $Constant);
18110 if(not defined $New_Value or $New_Value eq "") {
18111 next;
18112 }
18113
18114 if(constantFilter($Constant, $New_Value, $Level))
18115 { # separate binary and source problems
18116 next;
18117 }
18118
18119 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18120 "Target"=>$Constant,
18121 "New_Value"=>$New_Value );
18122 }
18123 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018124}
18125
18126sub convert_integer($)
18127{
18128 my $Value = $_[0];
18129 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018130 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018131 return hex($Value);
18132 }
18133 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018134 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018135 return oct($Value);
18136 }
18137 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018138 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018139 return oct($Value);
18140 }
18141 else {
18142 return $Value;
18143 }
18144}
18145
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018146sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018147{
18148 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018149 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018150 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018151 {
18152 if($LibVersion==1)
18153 {
18154 printMsg("WARNING", "checking headers only");
18155 $CheckHeadersOnly = 1;
18156 }
18157 else {
18158 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18159 }
18160 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018161
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018162 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018163 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018164 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018165
18166 if($CheckUndefined)
18167 {
18168 my %UndefinedLibs = ();
18169
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018170 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18171
18172 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018173 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018174 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018175 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018176 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018177 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018178 if($Symbol_Library{$LibVersion}{$Symbol}
18179 or $DepSymbol_Library{$LibVersion}{$Symbol})
18180 { # exported by target library
18181 next;
18182 }
18183 if(index($Symbol, '@')!=-1)
18184 { # exported default symbol version (@@)
18185 $Symbol=~s/\@/\@\@/;
18186 if($Symbol_Library{$LibVersion}{$Symbol}
18187 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18188 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018189 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018190 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018191 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18192 $UndefinedLibs{$Path} = 1;
18193 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018194 }
18195 }
18196 }
18197 if($ExtraInfo)
18198 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018199 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018200 {
18201 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018202 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018203 foreach (@Paths)
18204 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018205 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018206 my ($Dir, $Name) = separate_path($_);
18207
18208 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018209 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018210 }
18211
18212 $Name = parse_libname($Name, "name", $OStarget);
18213 $Name=~s/\Alib//;
18214
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018215 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018216 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018217
18218 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18219 {
18220 $LibString = " -L".esc($Dir).$LibString;
18221 }
18222
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018223 writeFile($ExtraInfo."/libs-string", $LibString);
18224 }
18225 }
18226 }
18227
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018228 if($ExtraInfo) {
18229 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18230 }
18231
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018232 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018233 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018234 if($#LibPaths!=-1)
18235 {
18236 if(not keys(%{$Symbol_Library{$LibVersion}}))
18237 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018238 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018239 printMsg("WARNING", "checking headers only");
18240 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018241 }
18242 }
18243 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018244
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018245 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018246 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018247}
18248
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018249my %Prefix_Lib_Map=(
18250 # symbols for autodetecting library dependencies (by prefix)
18251 "pthread_" => ["libpthread"],
18252 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18253 "cairo_" => ["libcairo"],
18254 "gtk_" => ["libgtk-x11-2.0"],
18255 "atk_" => ["libatk-1.0"],
18256 "gdk_" => ["libgdk-x11-2.0"],
18257 "gl" => ["libGL"],
18258 "glu" => ["libGLU"],
18259 "popt" => ["libpopt"],
18260 "Py" => ["libpython"],
18261 "jpeg_" => ["libjpeg"],
18262 "BZ2_" => ["libbz2"],
18263 "Fc" => ["libfontconfig"],
18264 "Xft" => ["libXft"],
18265 "SSL_" => ["libssl"],
18266 "sem_" => ["libpthread"],
18267 "snd_" => ["libasound"],
18268 "art_" => ["libart_lgpl_2"],
18269 "dbus_g" => ["libdbus-glib-1"],
18270 "GOMP_" => ["libgomp"],
18271 "omp_" => ["libgomp"],
18272 "cms" => ["liblcms"]
18273);
18274
18275my %Pattern_Lib_Map=(
18276 "SL[a-z]" => ["libslang"]
18277);
18278
18279my %Symbol_Lib_Map=(
18280 # symbols for autodetecting library dependencies (by name)
18281 "pow" => "libm",
18282 "fmod" => "libm",
18283 "sin" => "libm",
18284 "floor" => "libm",
18285 "cos" => "libm",
18286 "dlopen" => "libdl",
18287 "deflate" => "libz",
18288 "inflate" => "libz",
18289 "move_panel" => "libpanel",
18290 "XOpenDisplay" => "libX11",
18291 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018292 "clock_gettime" => "librt",
18293 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018294);
18295
18296sub find_SymbolLibs($$)
18297{
18298 my ($LibVersion, $Symbol) = @_;
18299
18300 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18301 { # debug symbols
18302 return ();
18303 }
18304
18305 my %Paths = ();
18306
18307 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18308 {
18309 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18310 $Paths{$Path} = 1;
18311 }
18312 }
18313
18314 if(my $SymbolPrefix = getPrefix($Symbol))
18315 {
18316 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18317 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18318 }
18319
18320 if(not keys(%Paths))
18321 {
18322 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18323 {
18324 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18325 {
18326 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18327 $Paths{$Path} = 1;
18328 }
18329 }
18330 }
18331 }
18332
18333 if(not keys(%Paths))
18334 {
18335 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18336 {
18337 if($Symbol=~/\A$Prefix/)
18338 {
18339 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18340 {
18341 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18342 $Paths{$Path} = 1;
18343 }
18344 }
18345 }
18346 }
18347 }
18348
18349 if(not keys(%Paths))
18350 {
18351 if($SymbolPrefix)
18352 { # try to find a library by symbol prefix
18353 if($SymbolPrefix eq "inotify" and
18354 index($Symbol, "\@GLIBC")!=-1)
18355 {
18356 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18357 $Paths{$Path} = 1;
18358 }
18359 }
18360 else
18361 {
18362 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18363 $Paths{$Path} = 1;
18364 }
18365 }
18366 }
18367 }
18368
18369 if(my @Paths = keys(%Paths)) {
18370 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18371 }
18372 }
18373 return keys(%Paths);
18374}
18375
18376sub get_LibPath_Prefix($$)
18377{
18378 my ($LibVersion, $Prefix) = @_;
18379
18380 $Prefix = lc($Prefix);
18381 $Prefix=~s/[_]+\Z//g;
18382
18383 foreach ("-2", "2", "-1", "1", "")
18384 { # libgnome-2.so
18385 # libxml2.so
18386 # libdbus-1.so
18387 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18388 return $Path;
18389 }
18390 }
18391 return "";
18392}
18393
18394sub getPrefix($)
18395{
18396 my $Str = $_[0];
18397 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18398 { # XmuValidArea: Xmu
18399 return $1;
18400 }
18401 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18402 { # snfReadFont: snf
18403 return $1;
18404 }
18405 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18406 { # XRRTimes: XRR
18407 return $1;
18408 }
18409 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18410 { # H5HF_delete: H5
18411 return $1;
18412 }
18413 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18414 { # alarm_event_add: alarm_
18415 return $1;
18416 }
18417 elsif($Str=~/\A(([a-z])\2{1,})/i)
18418 { # ffopen
18419 return $1;
18420 }
18421 return "";
18422}
18423
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018424sub getSymbolSize($$)
18425{ # size from the shared library
18426 my ($Symbol, $LibVersion) = @_;
18427 return 0 if(not $Symbol);
18428 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18429 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18430 {
18431 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18432 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18433 {
18434 if($Size<0) {
18435 return -$Size;
18436 }
18437 }
18438 }
18439 return 0;
18440}
18441
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018442sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018443{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18444 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018445 my ($Name, $Type) = @_;
18446
18447 # single
18448 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018449 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018450 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018451 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018452 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018453
18454 # double
18455 if($Name=~/$DEFAULT_STD_PARMS/)
18456 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018457 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018458 {
18459 my ($ShortName, $FuncParams) = split_Signature($Name);
18460
18461 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18462 {
18463 if(index($FParam, "<")!=-1)
18464 {
18465 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18466 my $FParam_N = canonifyName($FParam, "T");
18467 if($FParam_N ne $FParam) {
18468 $Name=~s/\Q$FParam\E/$FParam_N/g;
18469 }
18470 }
18471 }
18472 }
18473 elsif($Type eq "T")
18474 {
18475 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18476
18477 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018478 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018479 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018480 my $FParam = $TParams[0];
18481 foreach my $Pos (1 .. $#TParams)
18482 {
18483 my $TParam = $TParams[$Pos];
18484 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18485 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18486 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018487 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018488 }
18489 }
18490 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018491 if($Type eq "S") {
18492 return formatName($Name, "S");
18493 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018494 return $Name;
18495}
18496
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018497sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018498{
18499 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018500 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018501 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018502 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018503 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018504 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018505 next if($tr_name{$Symbol});
18506 $Symbol=~s/[\@\$]+(.*)\Z//;
18507 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018508 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018509 elsif(index($Symbol, "?")==0)
18510 {
18511 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018512 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018513 }
18514 else
18515 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018516 $tr_name{$Symbol} = $Symbol;
18517 $mangled_name_gcc{$Symbol} = $Symbol;
18518 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018519 }
18520 }
18521 if($#MnglNames1 > -1)
18522 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018523 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018524 foreach my $MnglName (@MnglNames1)
18525 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018526 if(my $Unmangled = pop(@UnmangledNames))
18527 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018528 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018529 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18530 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18531 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018532 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018533 and $tr_name{$MnglName}=~/vtable for (.+)/)
18534 { # bind class name and v-table symbol
18535 my $ClassName = $1;
18536 $ClassVTable{$ClassName} = $MnglName;
18537 $VTableClass{$MnglName} = $ClassName;
18538 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018539 }
18540 }
18541 }
18542 if($#MnglNames2 > -1)
18543 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018544 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018545 foreach my $MnglName (@MnglNames2)
18546 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018547 if(my $Unmangled = pop(@UnmangledNames))
18548 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018549 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018550 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18551 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018552 }
18553 }
18554 return \%tr_name;
18555}
18556
18557sub link_symbol($$$)
18558{
18559 my ($Symbol, $RunWith, $Deps) = @_;
18560 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18561 return 1;
18562 }
18563 if($Deps eq "+Deps")
18564 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018565 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018566 return 1;
18567 }
18568 }
18569 return 0;
18570}
18571
18572sub link_symbol_internal($$$)
18573{
18574 my ($Symbol, $RunWith, $Where) = @_;
18575 return 0 if(not $Where or not $Symbol);
18576 if($Where->{$RunWith}{$Symbol})
18577 { # the exact match by symbol name
18578 return 1;
18579 }
18580 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18581 { # indirect symbol version, i.e.
18582 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018583 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018584 if($Where->{$RunWith}{$VSym}) {
18585 return 1;
18586 }
18587 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018588 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018589 if($Sym and $Ver)
18590 { # search for the symbol with the same version
18591 # or without version
18592 if($Where->{$RunWith}{$Sym})
18593 { # old: foo@v|foo@@v
18594 # new: foo
18595 return 1;
18596 }
18597 if($Where->{$RunWith}{$Sym."\@".$Ver})
18598 { # old: foo|foo@@v
18599 # new: foo@v
18600 return 1;
18601 }
18602 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18603 { # old: foo|foo@v
18604 # new: foo@@v
18605 return 1;
18606 }
18607 }
18608 return 0;
18609}
18610
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018611sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018612{
18613 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018614 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018615 my @Imported = ();
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018616 if($OStarget eq "macos")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018617 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018618 my $NM = get_CmdPath("nm");
18619 if(not $NM) {
18620 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018621 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018622 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018623 while(<APP>)
18624 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018625 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018626 push(@Imported, $1);
18627 }
18628 }
18629 close(APP);
18630 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030018631 elsif($OStarget eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018632 {
18633 my $DumpBinCmd = get_CmdPath("dumpbin");
18634 if(not $DumpBinCmd) {
18635 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18636 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018637 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018638 while(<APP>)
18639 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018640 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18641 push(@Imported, $1);
18642 }
18643 }
18644 close(APP);
18645 }
18646 else
18647 {
18648 my $ReadelfCmd = get_CmdPath("readelf");
18649 if(not $ReadelfCmd) {
18650 exitStatus("Not_Found", "can't find \"readelf\"");
18651 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018652 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018653 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018654 while(<APP>)
18655 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018656 if(defined $symtab)
18657 { # do nothing with symtab
18658 if(index($_, "'.dynsym'")!=-1)
18659 { # dynamic table
18660 $symtab = undef;
18661 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018662 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018663 elsif(index($_, "'.symtab'")!=-1)
18664 { # symbol table
18665 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018666 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018667 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018668 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018669 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18670 if($Ndx eq "UND")
18671 { # only imported symbols
18672 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018673 }
18674 }
18675 }
18676 close(APP);
18677 }
18678 return @Imported;
18679}
18680
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018681my %ELF_BIND = map {$_=>1} (
18682 "WEAK",
18683 "GLOBAL"
18684);
18685
18686my %ELF_TYPE = map {$_=>1} (
18687 "FUNC",
18688 "IFUNC",
18689 "OBJECT",
18690 "COMMON"
18691);
18692
18693my %ELF_VIS = map {$_=>1} (
18694 "DEFAULT",
18695 "PROTECTED"
18696);
18697
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018698sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018699{ # read the line of 'readelf' output corresponding to the symbol
18700 my @Info = split(/\s+/, $_[0]);
18701 # Num: Value Size Type Bind Vis Ndx Name
18702 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018703 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018704 shift(@Info); # spaces
18705 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018706
18707 if($#Info==7)
18708 { # UND SYMBOL (N)
18709 if($Info[7]=~/\(\d+\)/) {
18710 pop(@Info);
18711 }
18712 }
18713
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018714 if($#Info!=6)
18715 { # other lines
18716 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018717 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018718 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018719 return () if(not defined $ELF_BIND{$Info[3]});
18720 return () if(not defined $ELF_VIS{$Info[4]});
18721 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18722 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18723 return ();
18724 }
18725 if($OStarget eq "symbian")
18726 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18727 if(index($Info[6], "_._.absent_export_")!=-1)
18728 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18729 return ();
18730 }
18731 $Info[6]=~s/\@.+//g; # remove version
18732 }
18733 if(index($Info[2], "0x") == 0)
18734 { # size == 0x3d158
18735 $Info[2] = hex($Info[2]);
18736 }
18737 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018738}
18739
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018740sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018741{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018742 my ($LibVersion, $Name) = @_;
18743 return "" if(not $LibVersion or not $Name);
18744 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18745 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018746 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018747 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18748}
18749
18750sub get_LibPath_I($$)
18751{
18752 my ($LibVersion, $Name) = @_;
18753 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018754 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018755 if(-f $Name)
18756 { # absolute path
18757 return $Name;
18758 }
18759 else
18760 { # broken
18761 return "";
18762 }
18763 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018764 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018765 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018766 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018767 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018768 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018769 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018770 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018771 }
18772 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18773 { # ldconfig default paths
18774 return $DefaultPath;
18775 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018776 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018777 { # search in default linker directories
18778 # and then in all system paths
18779 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018780 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018781 }
18782 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018783 if(not defined $Cache{"checkSystemFiles"}) {
18784 checkSystemFiles();
18785 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018786 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18787 return $AllObjects[0];
18788 }
18789 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18790 {
18791 if($ShortName ne $Name)
18792 { # FIXME: check this case
18793 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18794 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018795 }
18796 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018797 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018798 # can't find
18799 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018800}
18801
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018802sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018803{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018804 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18805 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018806
18807 my $Real_Path = realpath($Lib_Path);
18808
18809 if(not $Real_Path)
18810 { # broken link
18811 return ();
18812 }
18813
18814 my $Lib_Name = get_filename($Real_Path);
18815
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018816 if($ExtraInfo)
18817 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018818 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018819 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018820 }
18821
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018822 if($IsNeededLib)
18823 {
18824 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18825 return ();
18826 }
18827 }
18828 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018829 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018830
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018831 push(@RecurLib, $Lib_Name);
18832 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018833 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18834
18835 if(not $IsNeededLib)
18836 { # special cases: libstdc++ and libc
18837 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18838 {
18839 if($ShortName eq "libstdc++")
18840 { # libstdc++.so.6
18841 $STDCXX_TESTING = 1;
18842 }
18843 elsif($ShortName eq "libc")
18844 { # libc-2.11.3.so
18845 $GLIBC_TESTING = 1;
18846 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018847 }
18848 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018849 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018850 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018851 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018852 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018853 mkpath(get_dirname($DebugPath));
18854 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018855 if($OStarget eq "macos")
18856 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018857 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018858 if(not $NM) {
18859 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018860 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018861 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018862 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018863 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018864 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018865 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018866 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018867 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018868 else
18869 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018870 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018871 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018872 while(<LIB>)
18873 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018874 if($CheckUndefined)
18875 {
18876 if(not $IsNeededLib)
18877 {
18878 if(/ U _([\w\$]+)\s*\Z/)
18879 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018880 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018881 next;
18882 }
18883 }
18884 }
18885
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018886 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018887 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018888 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018889 if($IsNeededLib)
18890 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018891 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018892 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018893 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18894 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018895 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018896 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018897 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018898 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018899 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18900 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018901 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18902 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018903 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018904 setLanguage($LibVersion, "C++");
18905 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018906 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018907 }
18908 }
18909 }
18910 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018911
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018912 if($Deps)
18913 {
18914 if($LIB_TYPE eq "dynamic")
18915 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018916
18917 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018918 if(not $OtoolCmd) {
18919 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018920 }
18921
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018922 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18923 while(<LIB>)
18924 {
18925 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
18926 and $1 ne $Lib_Path) {
18927 $NeededLib{$1} = 1;
18928 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018929 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018930 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018931 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018932 }
18933 }
18934 elsif($OStarget eq "windows")
18935 { # Windows *.dll, *.lib
18936 my $DumpBinCmd = get_CmdPath("dumpbin");
18937 if(not $DumpBinCmd) {
18938 exitStatus("Not_Found", "can't find \"dumpbin\"");
18939 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018940 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018941 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018942 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018943 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018944 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018945 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018946 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018947 else
18948 { # write to pipe
18949 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018950 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018951 while(<LIB>)
18952 { # 1197 4AC 0000A620 SetThreadStackGuarantee
18953 # 1198 4AD SetThreadToken (forwarded to ...)
18954 # 3368 _o2i_ECPublicKey
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018955 # 1 0 00005B30 ??0?N = ... (with pdb)
18956 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*(?:=.+)?\Z/i
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018957 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040018958 or /\A\s*\d+\s+_([\w\?\@]+)\s*(?:=.+)?\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018959 { # dynamic, static and forwarded symbols
18960 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018961 if($IsNeededLib)
18962 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018963 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018964 {
18965 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
18966 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
18967 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018968 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018969 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018970 {
18971 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
18972 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018973 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18974 {
18975 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
18976 setLanguage($LibVersion, "C++");
18977 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018978 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018979 }
18980 }
18981 }
18982 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018983
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018984 if($Deps)
18985 {
18986 if($LIB_TYPE eq "dynamic")
18987 { # dependencies
18988 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18989 while(<LIB>)
18990 {
18991 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
18992 and $1 ne $Lib_Path) {
18993 $NeededLib{path_format($1, $OSgroup)} = 1;
18994 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018995 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018996 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018997 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018998 }
18999 }
19000 else
19001 { # Unix; *.so, *.a
19002 # Symbian: *.dso, *.lib
19003 my $ReadelfCmd = get_CmdPath("readelf");
19004 if(not $ReadelfCmd) {
19005 exitStatus("Not_Found", "can't find \"readelf\"");
19006 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019007 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019008 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019009 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019010 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019011 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019012 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019013 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019014 else
19015 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019016 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019017 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019018 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019019 while(<LIB>)
19020 {
19021 if($LIB_TYPE eq "dynamic")
19022 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019023 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019024 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019025 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019026 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019027 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019028 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019029 # do nothing with symtab
19030 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019031 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019032 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019033 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019034 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019035 next;
19036 }
19037 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019038 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019039 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019040 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019041 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019042 if($CheckUndefined)
19043 {
19044 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019045 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019046 }
19047 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019048 next;
19049 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019050 if($Bind eq "WEAK")
19051 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019052 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019053 if($Weak eq "-Weak")
19054 { # skip WEAK symbols
19055 next;
19056 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019057 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019058 my $Short = $Symbol;
19059 $Short=~s/\@.+//g;
19060 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019061 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019062 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19063 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019064 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019065 if($IsNeededLib)
19066 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019067 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019068 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019069 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19070 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019071 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019072 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019073 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019074 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019075 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19076 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19077 if($Vers)
19078 {
19079 if($LIB_EXT eq "so")
19080 { # value
19081 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19082 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19083 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019084 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019085 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19086 {
19087 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19088 setLanguage($LibVersion, "C++");
19089 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019090 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019091 }
19092 }
19093 }
19094 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019095
19096 if($Deps and $LIB_TYPE eq "dynamic")
19097 { # dynamic library specifics
19098 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19099 open(LIB, $Cmd." |");
19100
19101 while(<LIB>)
19102 {
19103 if(/NEEDED.+\[([^\[\]]+)\]/)
19104 { # dependencies:
19105 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19106 $NeededLib{$1} = 1;
19107 }
19108 }
19109
19110 close(LIB);
19111 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019112 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019113 if($Vers)
19114 {
19115 if(not $IsNeededLib and $LIB_EXT eq "so")
19116 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019117 my %Found = ();
19118
19119 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019120 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019121 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019122 next if(index($Symbol,"\@")==-1);
19123 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019124 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019125 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019126 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019127 if($Symbol_SameValue ne $Symbol
19128 and index($Symbol_SameValue,"\@")==-1)
19129 {
19130 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019131 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019132 last;
19133 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019134 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019135 }
19136 }
19137
19138 # default
19139 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19140 {
19141 next if(defined $Found{$Symbol});
19142 next if(index($Symbol,"\@\@")==-1);
19143
19144 if($Symbol=~/\A([^\@]*)\@\@/
19145 and not $SymVer{$LibVersion}{$1})
19146 {
19147 $SymVer{$LibVersion}{$1} = $Symbol;
19148 $Found{$Symbol} = 1;
19149 }
19150 }
19151
19152 # non-default
19153 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19154 {
19155 next if(defined $Found{$Symbol});
19156 next if(index($Symbol,"\@")==-1);
19157
19158 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19159 and not $SymVer{$LibVersion}{$1})
19160 {
19161 $SymVer{$LibVersion}{$1} = $Symbol;
19162 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019163 }
19164 }
19165 }
19166 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019167 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019168 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019169 foreach my $DyLib (sort keys(%NeededLib))
19170 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019171 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19172
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019173 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19174 {
19175 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19176 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19177 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019178 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019179 }
19180 }
19181 pop(@RecurLib);
19182 return $Library_Symbol{$LibVersion};
19183}
19184
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019185sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019186{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019187 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019188 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019189 return keys(%Prefixes);
19190}
19191
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019192sub get_prefixes_I($$)
19193{
19194 foreach my $P (@{$_[0]})
19195 {
19196 my @Parts = reverse(split(/[\/\\]+/, $P));
19197 my $Name = $Parts[0];
19198 foreach (1 .. $#Parts)
19199 {
19200 $_[1]->{$Name}{$P} = 1;
19201 last if($_>4 or $Parts[$_] eq "include");
19202 $Name = $Parts[$_].$SLASH.$Name;
19203 }
19204 }
19205}
19206
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019207sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019208{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019209 $Cache{"checkSystemFiles"} = 1;
19210
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019211 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019212
19213 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019214 {
19215 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019216
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019217 my @Files = cmd_find($DevelPath,"f");
19218 foreach my $Link (cmd_find($DevelPath,"l"))
19219 { # add symbolic links
19220 if(-f $Link) {
19221 push(@Files, $Link);
19222 }
19223 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019224
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019225 # search for headers in /usr/lib
19226 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19227 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19228 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019229
19230 # search for libraries in /usr/lib (including symbolic links)
19231 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19232 foreach my $Path (@Libs)
19233 {
19234 my $N = get_filename($Path);
19235 $SystemObjects{$N}{$Path} = 1;
19236 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019237 }
19238 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019239
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019240 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019241 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019242 next if(not -d $DevelPath);
19243 # search for all header files in the /usr/include
19244 # with or without extension (ncurses.h, QtCore, ...)
19245 push(@SysHeaders, cmd_find($DevelPath,"f"));
19246 foreach my $Link (cmd_find($DevelPath,"l"))
19247 { # add symbolic links
19248 if(-f $Link) {
19249 push(@SysHeaders, $Link);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019250 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019251 }
19252 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030019253 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019254}
19255
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019256sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019257{
19258 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019259 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019260 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19261 {
19262 if(not -e $Dest) {
19263 exitStatus("Access_Error", "can't access \'$Dest\'");
19264 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019265 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019266 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19267 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019268 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019269 }
19270 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019271 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019272}
19273
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019274sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019275{
19276 my ($Path, $LibVersion) = @_;
19277 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019278 my $Name = get_filename($Path);
19279 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019280 return 1;
19281 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019282 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019283 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19284 return 1;
19285 }
19286 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19287 {
19288 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19289 return 1;
19290 }
19291 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019292 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019293 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019294 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019295 return 1;
19296 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019297 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019298 return 1;
19299 }
19300 }
19301 return 0;
19302}
19303
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019304sub specificHeader($$)
19305{
19306 my ($Header, $Spec) = @_;
19307 my $Name = get_filename($Header);
19308
19309 if($Spec eq "windows")
19310 {# MS Windows
19311 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19312 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19313 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19314 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19315 my @Dirs = (
19316 "win32",
19317 "win64",
19318 "win",
19319 "windows",
19320 "msvcrt"
19321 ); # /gsf-win32/
19322 if(my $DIRs = join("|", @Dirs)) {
19323 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19324 }
19325 }
19326 elsif($Spec eq "macos")
19327 { # Mac OS
19328 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19329 }
19330
19331 return 0;
19332}
19333
19334sub skipAlienHeader($)
19335{
19336 my $Path = $_[0];
19337 my $Name = get_filename($Path);
19338 my $Dir = get_dirname($Path);
19339
19340 if($Tolerance=~/2/)
19341 { # 2 - skip internal headers
19342 my @Terms = (
19343 "p",
19344 "priv",
19345 "int",
19346 "impl",
19347 "implementation",
19348 "internal",
19349 "private",
19350 "old",
19351 "compat",
19352 "debug",
19353 "test",
19354 "gen"
19355 );
19356
19357 my @Dirs = (
19358 "private",
19359 "priv",
19360 "port",
19361 "impl",
19362 "internal",
19363 "detail",
19364 "details",
19365 "old",
19366 "compat",
19367 "debug",
19368 "config",
19369 "compiler",
19370 "platform",
19371 "test"
19372 );
19373
19374 if(my $TERMs = join("|", @Terms)) {
19375 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19376 }
19377 if(my $DIRs = join("|", @Dirs)) {
19378 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19379 }
19380
19381 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19382 }
19383
19384 if($Tolerance=~/1/)
19385 { # 1 - skip non-Linux headers
19386 if($OSgroup ne "windows")
19387 {
19388 if(specificHeader($Path, "windows")) {
19389 return 1;
19390 }
19391 }
19392 if($OSgroup ne "macos")
19393 {
19394 if(specificHeader($Path, "macos")) {
19395 return 1;
19396 }
19397 }
19398 }
19399
19400 # valid
19401 return 0;
19402}
19403
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019404sub skipHeader($$)
19405{
19406 my ($Path, $LibVersion) = @_;
19407 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019408 if(defined $Cache{"skipHeader"}{$Path}) {
19409 return $Cache{"skipHeader"}{$Path};
19410 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019411 if(defined $Tolerance and $Tolerance=~/1|2/)
19412 { # --tolerant
19413 if(skipAlienHeader($Path)) {
19414 return ($Cache{"skipHeader"}{$Path} = 1);
19415 }
19416 }
19417 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19418 return 0;
19419 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019420 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19421}
19422
19423sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019424{ # returns:
19425 # 1 - if header should NOT be included and checked
19426 # 2 - if header should NOT be included, but should be checked
19427 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019428 my $Name = get_filename($Path);
19429 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019430 return $Kind;
19431 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019432 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19433 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019434 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019435 if(index($Path, $D)!=-1)
19436 {
19437 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19438 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19439 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019440 }
19441 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019442 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19443 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019444 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019445 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19446 {
19447 if($Name=~/$P/) {
19448 return $Kind;
19449 }
19450 if($P=~/[\/\\]/ and $Path=~/$P/) {
19451 return $Kind;
19452 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019453 }
19454 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019455
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019456 return 0;
19457}
19458
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019459sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019460{
19461 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019462 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019463 { # system directory
19464 return;
19465 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019466 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019467 { # already registered
19468 return;
19469 }
19470 foreach my $Path (find_libs($Dir,"",1))
19471 {
19472 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019473 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019474 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019475 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019476 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19477}
19478
19479sub registerObject($$)
19480{
19481 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019482
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019483 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019484 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019485 if($OStarget=~/linux|bsd/i)
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019486 {
19487 if(my $SONAME = getSONAME($Path)) {
19488 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19489 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019490 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019491 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19492 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019493 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019494
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040019495 if(not $CheckedArch{$LibVersion} and -f $Path)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019496 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019497 if(my $ObjArch = getArch_Object($Path))
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019498 {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019499 if($ObjArch ne getArch_GCC($LibVersion))
19500 { # translation unit dump generated by the GCC compiler should correspond to the input objects
19501 $CheckedArch{$LibVersion} = 1;
19502 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 +040019503 }
19504 }
19505 }
19506}
19507
19508sub getArch_Object($)
19509{
19510 my $Path = $_[0];
19511
19512 my %MachineType = (
19513 "14C" => "x86",
19514 "8664" => "x86_64",
19515 "1C0" => "arm",
19516 "200" => "ia64"
19517 );
19518
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019519 my %ArchName = (
19520 "s390:31-bit" => "s390",
19521 "s390:64-bit" => "s390x",
19522 "powerpc:common" => "ppc32",
19523 "powerpc:common64" => "ppc64",
19524 "i386:x86-64" => "x86_64",
19525 "mips:3000" => "mips",
19526 "sparc:v8plus" => "sparcv9"
19527 );
19528
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019529 if($OStarget eq "windows")
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019530 {
19531 my $DumpbinCmd = get_CmdPath("dumpbin");
19532 if(not $DumpbinCmd) {
19533 exitStatus("Not_Found", "can't find \"dumpbin\"");
19534 }
19535
19536 my $Cmd = $DumpbinCmd." /headers \"$Path\"";
19537 my $Out = `$Cmd`;
19538
19539 if($Out=~/(\w+)\smachine/)
19540 {
19541 if(my $Type = $MachineType{uc($1)})
19542 {
19543 return $Type;
19544 }
19545 }
19546 }
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019547 elsif($OStarget=~/linux|bsd/)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019548 {
19549 my $ObjdumpCmd = get_CmdPath("objdump");
19550 if(not $ObjdumpCmd) {
19551 exitStatus("Not_Found", "can't find \"objdump\"");
19552 }
19553
19554 my $Cmd = $ObjdumpCmd." -f \"$Path\"";
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030019555
19556 if($OSgroup eq "windows") {
19557 $Cmd = "set LANG=$LOCALE & ".$Cmd;
19558 }
19559 else {
19560 $Cmd = "LANG=$LOCALE ".$Cmd;
19561 }
19562 my $Out = `$Cmd`;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019563
19564 if($Out=~/architecture:\s+([\w\-\:]+)/)
19565 {
19566 my $Arch = $1;
19567 if($Arch=~s/\:(.+)//)
19568 {
19569 my $Suffix = $1;
19570
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019571 if(my $Name = $ArchName{$Arch.":".$Suffix})
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019572 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019573 $Arch = $Name;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019574 }
19575 }
19576
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019577 if($Arch=~/i[3-6]86/) {
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019578 $Arch = "x86";
19579 }
19580
19581 if($Arch eq "x86-64") {
19582 $Arch = "x86_64";
19583 }
19584
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019585 if($Arch eq "ia64-elf64") {
19586 $Arch = "ia64";
19587 }
19588
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019589 return $Arch;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019590 }
19591 }
19592 else
19593 { # macos, etc.
19594 # TODO
19595 }
19596
19597 return undef;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019598}
19599
19600sub getSONAME($)
19601{
19602 my $Path = $_[0];
19603 return if(not $Path);
19604 if(defined $Cache{"getSONAME"}{$Path}) {
19605 return $Cache{"getSONAME"}{$Path};
19606 }
19607 my $ObjdumpCmd = get_CmdPath("objdump");
19608 if(not $ObjdumpCmd) {
19609 exitStatus("Not_Found", "can't find \"objdump\"");
19610 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019611 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019612 if($OSgroup eq "windows") {
19613 $SonameCmd .= " | find \"SONAME\"";
19614 }
19615 else {
19616 $SonameCmd .= " | grep SONAME";
19617 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019618 if(my $SonameInfo = `$SonameCmd`)
19619 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019620 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19621 return ($Cache{"getSONAME"}{$Path} = $1);
19622 }
19623 }
19624 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019625}
19626
19627sub getSOPaths_Dest($$)
19628{
19629 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019630 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019631 return ();
19632 }
19633 if(-f $Dest)
19634 {
19635 if(not parse_libname($Dest, "name", $OStarget)) {
19636 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19637 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019638 registerObject($Dest, $LibVersion);
19639 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019640 return ($Dest);
19641 }
19642 elsif(-d $Dest)
19643 {
19644 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019645 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019646 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019647 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19648 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019649 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019650 { # all files and symlinks that match the name of a library
19651 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19652 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019653 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019654 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019655 }
19656 }
19657 }
19658 else
19659 { # search for all files and symlinks
19660 foreach my $Path (find_libs($Dest,"",""))
19661 {
19662 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019663 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019664 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019665 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019666 }
19667 if($OSgroup eq "macos")
19668 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019669 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019670 {
19671 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019672 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019673 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019674 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19675 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019676 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019677 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019678 }
19679 }
19680 }
19681 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019682 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019683 }
19684 else {
19685 return ();
19686 }
19687}
19688
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019689sub isCyclical($$)
19690{
19691 my ($Stack, $Value) = @_;
19692 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019693}
19694
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019695sub getGCC_Opts($)
19696{ # to use in module
19697 my $LibVersion = $_[0];
19698
19699 my @Opts = ();
19700
19701 if($CompilerOptions{$LibVersion})
19702 { # user-defined options
19703 push(@Opts, $CompilerOptions{$LibVersion});
19704 }
19705 if($GccOptions)
19706 { # additional
19707 push(@Opts, $GccOptions);
19708 }
19709
19710 if(@Opts) {
19711 return join(" ", @Opts);
19712 }
19713
19714 return undef;
19715}
19716
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019717sub getArch_GCC($)
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019718{
19719 my $LibVersion = $_[0];
19720
19721 if(defined $Cache{"getArch_GCC"}{$LibVersion}) {
19722 return $Cache{"getArch_GCC"}{$LibVersion};
19723 }
19724
19725 my $Arch = undef;
19726
19727 if($GCC_PATH)
19728 {
19729 writeFile("$TMP_DIR/test.c", "int main(){return 0;}\n");
19730
19731 my $Cmd = $GCC_PATH." test.c -o test";
19732 if(my $Opts = getGCC_Opts($LibVersion))
19733 { # user-defined options
19734 $Cmd .= " ".$Opts;
19735 }
19736
19737 chdir($TMP_DIR);
19738 system($Cmd);
19739 chdir($ORIG_DIR);
19740
19741 $Arch = getArch_Object("$TMP_DIR/test");
19742
19743 unlink("$TMP_DIR/test.c");
19744 unlink("$TMP_DIR/test");
19745 }
19746
19747 if(not $Arch) {
19748 exitStatus("Error", "can't check ARCH type");
19749 }
19750
19751 return ($Cache{"getArch_GCC"}{$LibVersion} = $Arch);
19752}
19753
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019754sub detectWordSize($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019755{
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019756 my $LibVersion = $_[0];
19757
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019758 my $Size = undef;
19759
19760 # speed up detection
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019761 if(my $Arch = getArch($LibVersion))
19762 {
Andrey Ponomarenkob862d1d2014-03-06 21:08:21 +040019763 if($Arch=~/\A(x86_64|s390x|ppc64|ia64|alpha)\Z/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019764 $Size = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019765 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019766 elsif($Arch=~/\A(x86|s390|ppc32)\Z/) {
19767 $Size = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019768 }
19769 }
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019770
19771 if($GCC_PATH)
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019772 {
19773 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019774
19775 my $Cmd = $GCC_PATH." -E -dD empty.h";
19776 if(my $Opts = getGCC_Opts($LibVersion))
19777 { # user-defined options
19778 $Cmd .= " ".$Opts;
19779 }
19780
19781 chdir($TMP_DIR);
19782 my $Defines = `$Cmd`;
19783 chdir($ORIG_DIR);
19784
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019785 unlink("$TMP_DIR/empty.h");
19786
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019787 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
19788 { # GCC 4
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019789 $Size = $1;
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019790 }
19791 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
19792 { # GCC 3
19793 my $PTRDIFF = $1;
19794 if($PTRDIFF=~/long/) {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019795 $Size = "8";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019796 }
19797 else {
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019798 $Size = "4";
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019799 }
19800 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019801 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040019802
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019803 if(not $Size) {
19804 exitStatus("Error", "can't check WORD size");
19805 }
19806
19807 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019808}
19809
Andrey Ponomarenkod2ed4c62014-03-05 17:34:32 +040019810sub getWordSize($)
19811{ # to use in module
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019812 return $WORD_SIZE{$_[0]};
19813}
19814
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019815sub majorVersion($)
19816{
19817 my $V = $_[0];
19818 return 0 if(not $V);
19819 my @VParts = split(/\./, $V);
19820 return $VParts[0];
19821}
19822
19823sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019824{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019825 my ($V1, $V2) = @_;
19826 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019827 my @V1Parts = split(/\./, $V1);
19828 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019829 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
19830 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019831 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
19832 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
19833 }
19834 return -1 if($#V1Parts < $#V2Parts);
19835 return 1 if($#V1Parts > $#V2Parts);
19836 return 0;
19837}
19838
19839sub read_ABI_Dump($$)
19840{
19841 my ($LibVersion, $Path) = @_;
19842 return if(not $LibVersion or not -e $Path);
19843 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019844 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019845 { # input *.abi
19846 $FilePath = $Path;
19847 }
19848 else
19849 { # input *.abi.tar.gz
19850 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019851 if(not isDump_U($FilePath)) {
19852 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19853 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019854 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019855
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019856 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019857
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019858 my $Line = readLineNum($FilePath, 0);
19859 if($Line=~/xml/)
19860 { # XML format
19861 loadModule("XmlDump");
19862 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019863 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019864 else
19865 { # Perl Data::Dumper format (default)
19866 open(DUMP, $FilePath);
19867 local $/ = undef;
19868 my $Content = <DUMP>;
19869 close(DUMP);
19870
19871 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
19872 { # remove temp file
19873 unlink($FilePath);
19874 }
19875 if($Content!~/};\s*\Z/) {
19876 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19877 }
19878 $ABI = eval($Content);
19879 if(not $ABI) {
19880 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
19881 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019882 }
19883 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019884 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019885 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019886 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019887 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019888 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019889 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019890 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030019891 $UsedDump{$LibVersion}{"M"} = $ABI->{"LibraryName"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019892
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030019893 if($ABI->{"PublicABI"}) {
19894 $UsedDump{$LibVersion}{"Public"} = 1;
19895 }
19896
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019897 if($ABI->{"ABI_DUMP_VERSION"})
19898 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019899 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019900 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019901 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019902 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019903 }
19904 else
19905 { # support for old ABI dumps
19906 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019907 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019908 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019909 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019910 }
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030019911
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019912 if(majorVersion($DVersion)<2)
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030019913 {
19914 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 +040019915 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019916
19917 if(defined $ABI->{"ABI_DUMPER_VERSION"})
19918 { # DWARF ABI Dump
19919 $UseConv_Real{$LibVersion}{"P"} = 1;
19920 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19921
19922 $UsedDump{$LibVersion}{"DWARF"} = 1;
19923
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030019924 if(not $TargetComponent_Opt)
19925 {
19926 if($ABI->{"LibraryName"}=~/\.ko[\.\d]*\Z/) {
19927 $TargetComponent = "module";
19928 }
19929 else {
19930 $TargetComponent = "object";
19931 }
19932 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019933 }
19934
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019935 if(not checkDump($LibVersion, "2.11"))
19936 { # old ABI dumps
19937 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019938 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019939 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019940 { # ABI dump created with --binary option
19941 $UsedDump{$LibVersion}{"BinOnly"} = 1;
19942 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019943 else
19944 { # default
19945 $UsedDump{$LibVersion}{"SrcBin"} = 1;
19946 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019947
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019948 if(defined $ABI->{"Mode"}
19949 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019950 { # --ext option
19951 $ExtendedCheck = 1;
19952 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019953 if($ABI->{"Extra"}) {
19954 $ExtraDump = 1;
19955 }
19956
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019957 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019958 {
19959 $UsedDump{$LibVersion}{"L"} = $Lang;
19960 setLanguage($LibVersion, $Lang);
19961 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019962 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019963 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019964 }
19965 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019966 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019967 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019968 if(not $TInfo)
19969 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019970 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019971 }
19972 my %Tid_TDid = ();
19973 foreach my $TDid (keys(%{$TInfo}))
19974 {
19975 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
19976 {
19977 $MAX_ID = $Tid if($Tid>$MAX_ID);
19978 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019979 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019980 }
19981 }
19982 my %NewID = ();
19983 foreach my $Tid (keys(%Tid_TDid))
19984 {
19985 my @TDids = keys(%{$Tid_TDid{$Tid}});
19986 if($#TDids>=1)
19987 {
19988 foreach my $TDid (@TDids)
19989 {
19990 if($TDid) {
19991 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19992 }
19993 else
19994 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019995 my $ID = ++$MAX_ID;
19996
19997 $NewID{$TDid}{$Tid} = $ID;
19998 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
19999 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020000 }
20001 }
20002 }
20003 else
20004 {
20005 my $TDid = $TDids[0];
20006 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20007 }
20008 }
20009 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20010 {
20011 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20012 if(defined $Info{"BaseType"})
20013 {
20014 my $Bid = $Info{"BaseType"}{"Tid"};
20015 my $BDid = $Info{"BaseType"}{"TDid"};
20016 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020017 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020018 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20019 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20020 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020021 }
20022 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20023 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020024 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020025 read_Machine_DumpInfo($ABI, $LibVersion);
20026 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020027 if(not $SymbolInfo{$LibVersion})
20028 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020029 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020030 }
20031 if(not keys(%{$SymbolInfo{$LibVersion}}))
20032 { # validation of old-version dumps
20033 if(not $ExtendedCheck) {
20034 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20035 }
20036 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020037 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020038 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020039 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020040 else
20041 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020042 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020043 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020044 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020045 }
20046 if(not $DepSymbols)
20047 { # Cannot reconstruct DepSymbols. This may result in false
20048 # positives if the old dump is for library 2. Not a problem if
20049 # old dumps are only from old libraries.
20050 $DepSymbols = {};
20051 }
20052 foreach my $Symbol (keys(%{$DepSymbols})) {
20053 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20054 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020055 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020056 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020057
20058 if(my $V = $TargetVersion{$LibVersion}) {
20059 $Descriptor{$LibVersion}{"Version"} = $V;
20060 }
20061 else {
20062 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20063 }
20064
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020065 if(not $SkipTypes{$LibVersion})
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030020066 { # if not defined by -skip-types option
20067 if(defined $ABI->{"SkipTypes"})
20068 {
20069 foreach my $TName (keys(%{$ABI->{"SkipTypes"}}))
20070 {
20071 $SkipTypes{$LibVersion}{$TName} = 1;
20072 }
20073 }
20074 if(defined $ABI->{"OpaqueTypes"})
20075 { # support for old dumps
20076 foreach my $TName (keys(%{$ABI->{"OpaqueTypes"}}))
20077 {
20078 $SkipTypes{$LibVersion}{$TName} = 1;
20079 }
20080 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020081 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020082
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020083 if(not $SkipSymbols{$LibVersion})
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020084 { # if not defined by -skip-symbols option
20085 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
20086 if(not $SkipSymbols{$LibVersion})
20087 { # support for old dumps
20088 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
20089 }
20090 if(not $SkipSymbols{$LibVersion})
20091 { # support for old dumps
20092 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
20093 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020094 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020095 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030020096
20097 if(not $TargetHeaders{$LibVersion})
20098 { # if not defined by -headers-list option
20099 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20100 }
20101
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020102 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020103 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020104 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020105 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020106 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020107 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020108
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020109 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020110 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020111
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020112 if(not checkDump($LibVersion, "2.10.1")
20113 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020114 { # support for old ABI dumps: added target headers
20115 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020116 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020117 }
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030020118
20119 if(not $ABI->{"PublicABI"})
20120 {
20121 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20122 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20123 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020124 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020125 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020126 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020127 if(defined $ABI->{"GccConstants"})
20128 { # 3.0
20129 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20130 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20131 }
20132 }
20133
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020134 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020135 if(not $NestedNameSpaces{$LibVersion})
20136 { # support for old dumps
20137 # Cannot reconstruct NameSpaces. This may affect design
20138 # of the compatibility report.
20139 $NestedNameSpaces{$LibVersion} = {};
20140 }
20141 # target system type
20142 # needed to adopt HTML report
20143 if(not $DumpSystem)
20144 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020145 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020146 }
20147 # recreate environment
20148 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20149 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020150 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020151 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020152 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20153 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020154 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020155 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020156 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020157 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20158 {
20159 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20160 setLanguage($LibVersion, "C++");
20161 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020162 }
20163 }
20164 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020165 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20166 {
20167 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20168 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20169 }
20170 }
20171
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020172 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020173 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020174 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020175 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020176 {
20177 if(not $Symbol_Library{$LibVersion}{$MnglName}
20178 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20179 push(@VFunc, $MnglName);
20180 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020181 }
20182 }
20183 translateSymbols(@VFunc, $LibVersion);
20184 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020185 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20186
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020187 if(not checkDump($LibVersion, "3.0"))
20188 { # support for old ABI dumps
20189 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20190 {
20191 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20192 {
20193 if(ref($BaseType) eq "HASH") {
20194 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20195 }
20196 }
20197 }
20198 }
20199
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020200 if(not checkDump($LibVersion, "3.2"))
20201 { # support for old ABI dumps
20202 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20203 {
20204 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20205 {
20206 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20207 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20208 }
20209 }
20210 }
20211
20212 # repair target headers list
20213 delete($TargetHeaders{$LibVersion});
20214 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020215 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20216 }
20217 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20218 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020219 }
20220
20221 # non-target constants from anon enums
20222 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20223 {
20224 if(not $ExtraDump
20225 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20226 {
20227 delete($Constants{$LibVersion}{$Name});
20228 }
20229 }
20230 }
20231
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020232 if(not checkDump($LibVersion, "2.20"))
20233 { # support for old ABI dumps
20234 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20235 {
20236 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20237
20238 if($TType=~/Struct|Union|Enum|Typedef/)
20239 { # repair complex types first
20240 next;
20241 }
20242
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020243 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020244 {
20245 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20246 if($BType=~/Struct|Union|Enum/i)
20247 {
20248 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20249 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20250 }
20251 }
20252 }
20253 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20254 {
20255 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20256 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20257 if($TType=~/Struct|Union|Enum/) {
20258 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20259 }
20260 }
20261 }
20262
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020263 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020264 { # NOTE: order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020265 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20266 { # support for old ABI dumps < 2.0 (ACC 1.22)
20267 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20268 {
20269 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20270 {
20271 if($Access ne "public") {
20272 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20273 }
20274 }
20275 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20276 }
20277 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20278 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020279 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20280 { # support for old ABI dumps
20281 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20282 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020283 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20284 { # DWARF ABI Dumps
20285 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20286 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020287 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20288 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20289 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020290
20291 # support for old formatting of type names
20292 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = formatName($TypeInfo{$LibVersion}{$TypeId}{"Name"}, "T");
20293
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020294 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20295 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020296 {
Andrey Ponomarenko1b597c32015-11-11 12:57:44 +030020297 foreach my $SubId (keys(%{$TInfo{"Base"}}))
20298 {
20299 if($SubId eq $TypeId)
20300 { # Fix erroneus ABI dump
20301 delete($TypeInfo{$LibVersion}{$TypeId}{"Base"}{$SubId});
20302 next;
20303 }
20304
20305 $Class_SubClasses{$LibVersion}{$SubId}{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020306 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020307 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020308 if($TInfo{"Type"} eq "MethodPtr")
20309 {
20310 if(defined $TInfo{"Param"})
20311 { # support for old ABI dumps <= 1.17
20312 if(not defined $TInfo{"Param"}{"0"})
20313 {
20314 my $Max = keys(%{$TInfo{"Param"}});
20315 foreach my $Pos (1 .. $Max) {
20316 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20317 }
20318 delete($TInfo{"Param"}{$Max});
20319 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20320 }
20321 }
20322 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020323 if($TInfo{"BaseType"} eq $TypeId)
20324 { # fix ABI dump
20325 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20326 }
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020327
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020328 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020329 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020330 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020331 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020332 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20333 if(not $BName)
20334 { # broken type
20335 next;
20336 }
20337 if($TInfo{"Name"} eq $BName)
20338 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020339 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020340 next;
20341 }
20342 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20343 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020344 }
20345 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020346 }
20347 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20348 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkodfd12452015-11-12 15:49:25 +030020349 $TName_Tid{$LibVersion}{$TInfo{"Name"}} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020350 }
20351 }
20352
20353 if(not checkDump($LibVersion, "2.15"))
20354 { # support for old ABI dumps
20355 my %Dups = ();
20356 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20357 {
20358 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020359 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020360 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20361 { # remove template decls
20362 delete($SymbolInfo{$LibVersion}{$InfoId});
20363 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020364 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020365 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020366 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20367 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020368 { # templates
20369 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020370 }
20371 }
20372 }
20373
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020374 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20375 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020376 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20377 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20378 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20379 { # support for old ABI dumps (< 3.1)
20380 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20381 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20382 { # add "this" first parameter
20383 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20384 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20385
20386 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20387 {
20388 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20389 foreach my $Pos (reverse(0 .. $#Pos)) {
20390 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20391 }
20392 }
20393 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20394 }
20395 }
20396
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020397 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20398 { # ABI dumps have no mangled names for C-functions
20399 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20400 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020401 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20402 { # support for old ABI dumps
20403 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20404 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020405 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20406 { # DWARF ABI Dumps
20407 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20408 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020409 }
20410
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020411 $Descriptor{$LibVersion}{"Dump"} = 1;
20412}
20413
20414sub read_Machine_DumpInfo($$)
20415{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020416 my ($ABI, $LibVersion) = @_;
20417 if($ABI->{"Arch"}) {
20418 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020419 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020420 if($ABI->{"WordSize"}) {
20421 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020422 }
20423 else
20424 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020425 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020426 }
20427 if(not $WORD_SIZE{$LibVersion})
20428 { # support for old dumps (<1.23)
20429 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20430 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020431 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020432 }
20433 else
20434 {
20435 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020436 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020437 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020438 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20439 { # any "pointer"-type
20440 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020441 last;
20442 }
20443 }
20444 if($PSize)
20445 { # a pointer type size
20446 $WORD_SIZE{$LibVersion} = $PSize;
20447 }
20448 else {
20449 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20450 }
20451 }
20452 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020453 if($ABI->{"GccVersion"}) {
20454 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020455 }
20456}
20457
20458sub read_Libs_DumpInfo($$)
20459{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020460 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020461 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20462 if(not $Library_Symbol{$LibVersion})
20463 { # support for old dumps
20464 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20465 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020466 if(keys(%{$Library_Symbol{$LibVersion}})
20467 and not $DumpAPI) {
20468 $Descriptor{$LibVersion}{"Libs"} = "OK";
20469 }
20470}
20471
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020472sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020473{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020474 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020475
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020476 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020477 and not $DumpAPI) {
20478 $Descriptor{$LibVersion}{"Headers"} = "OK";
20479 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020480 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020481 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020482 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020483 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020484 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020485
20486 if(keys(%{$ABI->{"Sources"}})
20487 and not $DumpAPI) {
20488 $Descriptor{$LibVersion}{"Sources"} = "OK";
20489 }
20490 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
Andrey Ponomarenko6ed91e72015-08-14 17:19:55 +030020491 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020492 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20493 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20494 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020495}
20496
20497sub find_libs($$$)
20498{
20499 my ($Path, $Type, $MaxDepth) = @_;
20500 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020501 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020502}
20503
20504sub createDescriptor($$)
20505{
20506 my ($LibVersion, $Path) = @_;
20507 if(not $LibVersion or not $Path
20508 or not -e $Path) {
20509 return "";
20510 }
20511 if(-d $Path)
20512 { # directory with headers files and shared objects
20513 return "
20514 <version>
20515 ".$TargetVersion{$LibVersion}."
20516 </version>
20517
20518 <headers>
20519 $Path
20520 </headers>
20521
20522 <libs>
20523 $Path
20524 </libs>";
20525 }
20526 else
20527 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020528 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020529 { # standard XML-descriptor
20530 return readFile($Path);
20531 }
20532 elsif(is_header($Path, 2, $LibVersion))
20533 { # header file
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020534 $CheckHeadersOnly = 1;
20535
20536 if($LibVersion==1) {
20537 $TargetVersion{$LibVersion} = "X";
20538 }
20539
20540 if($LibVersion==2) {
20541 $TargetVersion{$LibVersion} = "Y";
20542 }
20543
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020544 return "
20545 <version>
20546 ".$TargetVersion{$LibVersion}."
20547 </version>
20548
20549 <headers>
20550 $Path
20551 </headers>
20552
20553 <libs>
20554 none
20555 </libs>";
20556 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020557 else
20558 { # standard XML-descriptor
20559 return readFile($Path);
20560 }
20561 }
20562}
20563
20564sub detect_lib_default_paths()
20565{
20566 my %LPaths = ();
20567 if($OSgroup eq "bsd")
20568 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020569 if(my $LdConfig = get_CmdPath("ldconfig"))
20570 {
20571 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20572 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020573 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20574 {
20575 my $Name = "lib".$1;
20576 if(not defined $LPaths{$Name}) {
20577 $LPaths{$Name} = $2;
20578 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020579 }
20580 }
20581 }
20582 else {
20583 printMsg("WARNING", "can't find ldconfig");
20584 }
20585 }
20586 else
20587 {
20588 if(my $LdConfig = get_CmdPath("ldconfig"))
20589 {
20590 if($SystemRoot and $OSgroup eq "linux")
20591 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20592 if(-e $SystemRoot."/etc/ld.so.conf") {
20593 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20594 }
20595 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020596 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20597 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020598 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20599 {
20600 my ($Name, $Path) = ($1, $2);
20601 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020602 if(not defined $LPaths{$Name})
20603 { # get first element from the list of available paths
20604
20605 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20606 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20607 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20608
20609 $LPaths{$Name} = $Path;
20610 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020611 }
20612 }
20613 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020614 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020615 printMsg("WARNING", "can't find ldconfig");
20616 }
20617 }
20618 return \%LPaths;
20619}
20620
20621sub detect_bin_default_paths()
20622{
20623 my $EnvPaths = $ENV{"PATH"};
20624 if($OSgroup eq "beos") {
20625 $EnvPaths.=":".$ENV{"BETOOLS"};
20626 }
20627 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020628 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020629 {
20630 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020631 next if(not $Path);
20632 if($SystemRoot
20633 and $Path=~/\A\Q$SystemRoot\E\//)
20634 { # do NOT use binaries from target system
20635 next;
20636 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020637 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020638 }
20639}
20640
20641sub detect_inc_default_paths()
20642{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020643 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020644 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020645 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020646 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020647 next if(index($Line, "/cc1plus ")!=-1);
20648
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020649 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20650 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020651 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020652 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020653 if(index($Path, "c++")!=-1
20654 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020655 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020656 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020657 if(not defined $MAIN_CPP_DIR
20658 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20659 $MAIN_CPP_DIR = $Path;
20660 }
20661 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020662 elsif(index($Path, "gcc")!=-1) {
20663 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020664 }
20665 else
20666 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020667 if($Path=~/local[\/\\]+include/)
20668 { # local paths
20669 next;
20670 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020671 if($SystemRoot
20672 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20673 { # The GCC include path for user headers is not a part of the system root
20674 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20675 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20676 next;
20677 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020678 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020679 }
20680 }
20681 }
20682 unlink("$TMP_DIR/empty.h");
20683 return %DPaths;
20684}
20685
20686sub detect_default_paths($)
20687{
20688 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20689 my $Search = $_[0];
20690 if($Search!~/inc/) {
20691 $HSearch = 0;
20692 }
20693 if($Search!~/lib/) {
20694 $LSearch = 0;
20695 }
20696 if($Search!~/bin/) {
20697 $BSearch = 0;
20698 }
20699 if($Search!~/gcc/) {
20700 $GSearch = 0;
20701 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020702 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020703 { # <search_headers> section of the XML descriptor
20704 # do NOT search for systems headers
20705 $HSearch = 0;
20706 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020707 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenko6fce0fa2015-08-25 19:52:27 +030020708 { # <search_libs> section of the XML descriptor
20709 # do NOT search for systems libraries
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020710 $LSearch = 0;
20711 }
20712 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20713 { # additional search paths
20714 next if($Type eq "include" and not $HSearch);
20715 next if($Type eq "lib" and not $LSearch);
20716 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020717 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020718 }
20719 if($OSgroup ne "windows")
20720 { # unix-like
20721 foreach my $Type ("include", "lib", "bin")
20722 { # automatic detection of system "devel" directories
20723 next if($Type eq "include" and not $HSearch);
20724 next if($Type eq "lib" and not $LSearch);
20725 next if($Type eq "bin" and not $BSearch);
20726 my ($UsrDir, $RootDir) = ("/usr", "/");
20727 if($SystemRoot and $Type ne "bin")
20728 { # 1. search for target headers and libraries
20729 # 2. use host commands: ldconfig, readelf, etc.
20730 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20731 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020732 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020733 if(-d $RootDir."/".$Type)
20734 { # if "/lib" is symbolic link
20735 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020736 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020737 }
20738 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020739 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020740 }
20741 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020742 if(-d $UsrDir)
20743 {
20744 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020745 if(-d $UsrDir."/".$Type)
20746 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020747 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020748 }
20749 }
20750 }
20751 }
20752 if($BSearch)
20753 {
20754 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020755 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020756 }
20757 # check environment variables
20758 if($OSgroup eq "beos")
20759 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020760 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020761 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020762 if($_ eq ".") {
20763 next;
20764 }
20765 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20766 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20767 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020768 }
20769 }
20770 if($HSearch)
20771 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020772 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20773 split(/:|;/, $ENV{"BEINCLUDES"})
20774 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020775 }
20776 if($LSearch)
20777 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020778 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20779 split(/:|;/, $ENV{"BELIBRARIES"}),
20780 split(/:|;/, $ENV{"LIBRARY_PATH"})
20781 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020782 }
20783 }
20784 if($LSearch)
20785 { # using linker to get system paths
20786 if(my $LPaths = detect_lib_default_paths())
20787 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020788 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020789 foreach my $Name (keys(%{$LPaths}))
20790 {
20791 if($SystemRoot
20792 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20793 { # wrong ldconfig configuration
20794 # check your <sysroot>/etc/ld.so.conf
20795 next;
20796 }
20797 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020798 if(my $Dir = get_dirname($LPaths->{$Name})) {
20799 $Dirs{$Dir} = 1;
20800 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020801 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020802 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020803 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020804 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020805 }
20806 if($BSearch)
20807 {
20808 if($CrossGcc)
20809 { # --cross-gcc=arm-linux-gcc
20810 if(-e $CrossGcc)
20811 { # absolute or relative path
20812 $GCC_PATH = get_abs_path($CrossGcc);
20813 }
20814 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20815 { # command name
20816 $GCC_PATH = $CrossGcc;
20817 }
20818 else {
20819 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20820 }
20821 if($GCC_PATH=~/\s/) {
20822 $GCC_PATH = "\"".$GCC_PATH."\"";
20823 }
20824 }
20825 }
20826 if($GSearch)
20827 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020828 if(not $CrossGcc)
20829 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020830 $GCC_PATH = get_CmdPath("gcc");
20831 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020832 if(not $GCC_PATH)
20833 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020834 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020835 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020836 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020837 { # select the latest version
20838 @GCCs = sort {$b cmp $a} @GCCs;
20839 if(check_gcc($GCCs[0], "3"))
20840 {
20841 $GCC_PATH = $GCCs[0];
20842 last;
20843 }
20844 }
20845 }
20846 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020847 if(not $GCC_PATH) {
20848 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
20849 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020850
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020851 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020852 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020853 my $GccTarget = get_dumpmachine($GCC_PATH);
20854
20855 if($GccTarget=~/linux/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020856 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020857 $OStarget = "linux";
20858 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020859 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020860 elsif($GccTarget=~/symbian/)
20861 {
20862 $OStarget = "symbian";
20863 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
20864 }
20865
20866 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget, target: ".getArch_GCC(1).")");
20867
20868 # check GCC version
20869 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
20870 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
20871 # introduced in 4.8
20872 # fixed in 4.8.3
20873 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update or downgrade GCC or use a local installation by --gcc-path=PATH option.");
20874 $EMERGENCY_MODE_48 = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020875 }
20876 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020877 else {
20878 exitStatus("Error", "something is going wrong with the GCC compiler");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020879 }
20880 }
20881 if($HSearch)
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030020882 {
20883 # GCC standard paths
20884 if($GCC_PATH and not $NoStdInc)
20885 {
20886 my %DPaths = detect_inc_default_paths();
20887 @DefaultCppPaths = @{$DPaths{"Cpp"}};
20888 @DefaultGccPaths = @{$DPaths{"Gcc"}};
20889 @DefaultIncPaths = @{$DPaths{"Inc"}};
20890 push_U($SystemPaths{"include"}, @DefaultIncPaths);
20891 }
20892
20893 # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020894 my $IncPath = "/usr/include";
20895 if($SystemRoot) {
20896 $IncPath = $SystemRoot.$IncPath;
20897 }
20898 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020899 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020900 }
20901 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020902
20903 if($ExtraInfo)
20904 {
20905 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
20906 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
20907 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020908}
20909
20910sub getLIB_EXT($)
20911{
20912 my $Target = $_[0];
20913 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
20914 return $Ext;
20915 }
20916 return $OS_LibExt{$LIB_TYPE}{"default"};
20917}
20918
20919sub getAR_EXT($)
20920{
20921 my $Target = $_[0];
20922 if(my $Ext = $OS_Archive{$Target}) {
20923 return $Ext;
20924 }
20925 return $OS_Archive{"default"};
20926}
20927
20928sub get_dumpversion($)
20929{
20930 my $Cmd = $_[0];
20931 return "" if(not $Cmd);
20932 if($Cache{"get_dumpversion"}{$Cmd}) {
20933 return $Cache{"get_dumpversion"}{$Cmd};
20934 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020935 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020936 chomp($V);
20937 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
20938}
20939
20940sub get_dumpmachine($)
20941{
20942 my $Cmd = $_[0];
20943 return "" if(not $Cmd);
20944 if($Cache{"get_dumpmachine"}{$Cmd}) {
20945 return $Cache{"get_dumpmachine"}{$Cmd};
20946 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020947 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020948 chomp($Machine);
20949 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
20950}
20951
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020952sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020953{
20954 my $Cmd = $_[0];
20955 return "" if(not $Cmd);
20956 my @Options = (
20957 "--version",
20958 "-help"
20959 );
20960 foreach my $Opt (@Options)
20961 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020962 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020963 if($Info) {
20964 return 1;
20965 }
20966 }
20967 return 0;
20968}
20969
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020970sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020971{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020972 my ($Cmd, $ReqVer) = @_;
20973 return 0 if(not $Cmd or not $ReqVer);
20974 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
20975 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020976 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020977 if(my $GccVer = get_dumpversion($Cmd))
20978 {
20979 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
20980 if(cmpVersions($GccVer, $ReqVer)>=0) {
20981 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
20982 }
20983 }
20984 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020985}
20986
20987sub get_depth($)
20988{
20989 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020990 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020991 }
20992 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
20993}
20994
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020995sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020996{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020997 return if($Cache{"registerGccHeaders"}); # this function should be called once
20998
20999 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021000 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021001 my @Headers = cmd_find($Path,"f");
21002 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21003 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021004 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021005 my $FileName = get_filename($HPath);
21006 if(not defined $DefaultGccHeader{$FileName})
21007 { # skip duplicated
21008 $DefaultGccHeader{$FileName} = $HPath;
21009 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021010 }
21011 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021012 $Cache{"registerGccHeaders"} = 1;
21013}
21014
21015sub registerCppHeaders()
21016{
21017 return if($Cache{"registerCppHeaders"}); # this function should be called once
21018
21019 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021020 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021021 my @Headers = cmd_find($CppDir,"f");
21022 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21023 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021024 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021025 my $FileName = get_filename($Path);
21026 if(not defined $DefaultCppHeader{$FileName})
21027 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021028 $DefaultCppHeader{$FileName} = $Path;
21029 }
21030 }
21031 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021032 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021033}
21034
21035sub parse_libname($$$)
21036{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021037 return "" if(not $_[0]);
21038 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21039 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021040 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021041 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21042}
21043
21044sub parse_libname_I($$$)
21045{
21046 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021047
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021048 if($Target eq "symbian") {
21049 return parse_libname_symbian($Name, $Type);
21050 }
21051 elsif($Target eq "windows") {
21052 return parse_libname_windows($Name, $Type);
21053 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021054
21055 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021056 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021057 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021058 { # libSDL-1.2.so.0.7.1
21059 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021060 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021061 if($Type eq "name")
21062 { # libSDL-1.2
21063 # libwbxml2
21064 return $2;
21065 }
21066 elsif($Type eq "name+ext")
21067 { # libSDL-1.2.so
21068 # libwbxml2.so
21069 return $1;
21070 }
21071 elsif($Type eq "version")
21072 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021073 if(defined $7
21074 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021075 { # 0.7.1
21076 return $7;
21077 }
21078 else
21079 { # libc-2.5.so (=>2.5 version)
21080 my $MV = $5;
21081 $MV=~s/\A[\-\_]+//g;
21082 return $MV;
21083 }
21084 }
21085 elsif($Type eq "short")
21086 { # libSDL
21087 # libwbxml2
21088 return $3;
21089 }
21090 elsif($Type eq "shortest")
21091 { # SDL
21092 # wbxml
21093 return shortest_name($3);
21094 }
21095 }
21096 return "";# error
21097}
21098
21099sub parse_libname_symbian($$)
21100{
21101 my ($Name, $Type) = @_;
21102 my $Ext = getLIB_EXT("symbian");
21103 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21104 { # libpthread{00010001}.dso
21105 if($Type eq "name")
21106 { # libpthread{00010001}
21107 return $2;
21108 }
21109 elsif($Type eq "name+ext")
21110 { # libpthread{00010001}.dso
21111 return $1;
21112 }
21113 elsif($Type eq "version")
21114 { # 00010001
21115 my $V = $4;
21116 $V=~s/\{(.+)\}/$1/;
21117 return $V;
21118 }
21119 elsif($Type eq "short")
21120 { # libpthread
21121 return $3;
21122 }
21123 elsif($Type eq "shortest")
21124 { # pthread
21125 return shortest_name($3);
21126 }
21127 }
21128 return "";# error
21129}
21130
21131sub parse_libname_windows($$)
21132{
21133 my ($Name, $Type) = @_;
21134 my $Ext = getLIB_EXT("windows");
21135 if($Name=~/((.+?)\.$Ext)\Z/)
21136 { # netapi32.dll
21137 if($Type eq "name")
21138 { # netapi32
21139 return $2;
21140 }
21141 elsif($Type eq "name+ext")
21142 { # netapi32.dll
21143 return $1;
21144 }
21145 elsif($Type eq "version")
21146 { # DLL version embedded
21147 # at binary-level
21148 return "";
21149 }
21150 elsif($Type eq "short")
21151 { # netapi32
21152 return $2;
21153 }
21154 elsif($Type eq "shortest")
21155 { # netapi
21156 return shortest_name($2);
21157 }
21158 }
21159 return "";# error
21160}
21161
21162sub shortest_name($)
21163{
21164 my $Name = $_[0];
21165 # remove prefix
21166 $Name=~s/\A(lib|open)//;
21167 # remove suffix
21168 $Name=~s/[\W\d_]+\Z//i;
21169 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21170 return $Name;
21171}
21172
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021173sub createSymbolsList($$$$$)
21174{
21175 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021176
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021177 read_ABI_Dump(1, $DPath);
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021178 prepareSymbols(1);
21179
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021180 my %SymbolHeaderLib = ();
21181 my $Total = 0;
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021182
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021183 # Get List
21184 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21185 {
21186 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021187 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021188 next;
21189 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021190 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021191 { # skip other symbols
21192 next;
21193 }
21194 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21195 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021196 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021197 next;
21198 }
21199 my $DyLib = $Symbol_Library{1}{$Symbol};
21200 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021201 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021202 next;
21203 }
21204 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21205 $Total+=1;
21206 }
21207 # Draw List
21208 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21209 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21210 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21211 {
21212 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21213 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021214 my %NS_Symbol = ();
21215 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021216 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021217 }
21218 foreach my $NameSpace (sort keys(%NS_Symbol))
21219 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021220 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021221 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21222 foreach my $Symbol (@SortedInterfaces)
21223 {
21224 my $SubReport = "";
21225 my $Signature = get_Signature($Symbol, 1);
21226 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021227 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021228 }
21229 if($Symbol=~/\A(_Z|\?)/)
21230 {
21231 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021232 $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 +040021233 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021234 else {
21235 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21236 }
21237 }
21238 else
21239 {
21240 if($Signature) {
21241 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21242 }
21243 else {
21244 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21245 }
21246 }
21247 $SYMBOLS_LIST .= $SubReport;
21248 }
21249 }
21250 $SYMBOLS_LIST .= "<br/>\n";
21251 }
21252 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021253 # clear info
21254 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21255 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21256 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21257 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021258 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021259 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021260 my $CssStyles = readModule("Styles", "SymbolsList.css");
21261 my $JScripts = readModule("Scripts", "Sections.js");
21262 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021263 my $Title = "$LName: public symbols";
21264 my $Keywords = "$LName, API, symbols";
21265 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021266 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021267 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko41834e32015-09-04 12:30:41 +030021268 <br/><br/>\n".getReportFooter()."
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030021269 </body></html>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021270 writeFile($SaveTo, $SYMBOLS_LIST);
21271}
21272
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021273sub add_target_libs($)
21274{
21275 foreach (@{$_[0]}) {
21276 $TargetLibs{$_} = 1;
21277 }
21278}
21279
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021280sub is_target_lib($)
21281{
21282 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021283 if(not $LName) {
21284 return 0;
21285 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021286 if($TargetLibraryName
21287 and $LName!~/\Q$TargetLibraryName\E/) {
21288 return 0;
21289 }
21290 if(keys(%TargetLibs)
21291 and not $TargetLibs{$LName}
21292 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21293 return 0;
21294 }
21295 return 1;
21296}
21297
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021298sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021299{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021300 my ($H, $V) = @_;
21301 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021302 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021303 if($TargetHeaders{$V}{$H}) {
21304 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021305 }
21306 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021307 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021308}
21309
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021310sub readLibs($)
21311{
21312 my $LibVersion = $_[0];
21313 if($OStarget eq "windows")
21314 { # dumpbin.exe will crash
21315 # without VS Environment
21316 check_win32_env();
21317 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021318 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021319 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021320 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021321}
21322
21323sub dump_sorting($)
21324{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021325 my $Hash = $_[0];
21326 return [] if(not $Hash);
21327 my @Keys = keys(%{$Hash});
21328 return [] if($#Keys<0);
21329 if($Keys[0]=~/\A\d+\Z/)
21330 { # numbers
21331 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021332 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021333 else
21334 { # strings
21335 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021336 }
21337}
21338
21339sub printMsg($$)
21340{
21341 my ($Type, $Msg) = @_;
21342 if($Type!~/\AINFO/) {
21343 $Msg = $Type.": ".$Msg;
21344 }
21345 if($Type!~/_C\Z/) {
21346 $Msg .= "\n";
21347 }
21348 if($Quiet)
21349 { # --quiet option
21350 appendFile($COMMON_LOG_PATH, $Msg);
21351 }
21352 else
21353 {
21354 if($Type eq "ERROR") {
21355 print STDERR $Msg;
21356 }
21357 else {
21358 print $Msg;
21359 }
21360 }
21361}
21362
21363sub exitStatus($$)
21364{
21365 my ($Code, $Msg) = @_;
21366 printMsg("ERROR", $Msg);
21367 exit($ERROR_CODE{$Code});
21368}
21369
21370sub exitReport()
21371{ # the tool has run without any errors
21372 printReport();
21373 if($COMPILE_ERRORS)
21374 { # errors in headers may add false positives/negatives
21375 exit($ERROR_CODE{"Compile_Error"});
21376 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021377 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21378 { # --binary
21379 exit($ERROR_CODE{"Incompatible"});
21380 }
21381 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21382 { # --source
21383 exit($ERROR_CODE{"Incompatible"});
21384 }
21385 elsif($RESULT{"Source"}{"Problems"}
21386 or $RESULT{"Binary"}{"Problems"})
21387 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021388 exit($ERROR_CODE{"Incompatible"});
21389 }
21390 else {
21391 exit($ERROR_CODE{"Compatible"});
21392 }
21393}
21394
21395sub readRules($)
21396{
21397 my $Kind = $_[0];
21398 if(not -f $RULES_PATH{$Kind}) {
21399 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21400 }
21401 my $Content = readFile($RULES_PATH{$Kind});
21402 while(my $Rule = parseTag(\$Content, "rule"))
21403 {
21404 my $RId = parseTag(\$Rule, "id");
21405 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21406 foreach my $Prop (@Properties) {
21407 if(my $Value = parseTag(\$Rule, lc($Prop)))
21408 {
21409 $Value=~s/\n[ ]*//;
21410 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21411 }
21412 }
21413 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21414 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21415 }
21416 else {
21417 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21418 }
21419 }
21420}
21421
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021422sub getReportPath($)
21423{
21424 my $Level = $_[0];
21425 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21426 if($Level eq "Binary")
21427 {
21428 if($BinaryReportPath)
21429 { # --bin-report-path
21430 return $BinaryReportPath;
21431 }
21432 elsif($OutputReportPath)
21433 { # --report-path
21434 return $OutputReportPath;
21435 }
21436 else
21437 { # default
21438 return $Dir."/abi_compat_report.$ReportFormat";
21439 }
21440 }
21441 elsif($Level eq "Source")
21442 {
21443 if($SourceReportPath)
21444 { # --src-report-path
21445 return $SourceReportPath;
21446 }
21447 elsif($OutputReportPath)
21448 { # --report-path
21449 return $OutputReportPath;
21450 }
21451 else
21452 { # default
21453 return $Dir."/src_compat_report.$ReportFormat";
21454 }
21455 }
21456 else
21457 {
21458 if($OutputReportPath)
21459 { # --report-path
21460 return $OutputReportPath;
21461 }
21462 else
21463 { # default
21464 return $Dir."/compat_report.$ReportFormat";
21465 }
21466 }
21467}
21468
21469sub printStatMsg($)
21470{
21471 my $Level = $_[0];
21472 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21473}
21474
21475sub listAffected($)
21476{
21477 my $Level = $_[0];
21478 my $List = "";
21479 foreach (keys(%{$TotalAffected{$Level}}))
21480 {
21481 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21482 { # skip "Low"-severity problems
21483 next;
21484 }
21485 $List .= "$_\n";
21486 }
21487 my $Dir = get_dirname(getReportPath($Level));
21488 if($Level eq "Binary") {
21489 writeFile($Dir."/abi_affected.txt", $List);
21490 }
21491 elsif($Level eq "Source") {
21492 writeFile($Dir."/src_affected.txt", $List);
21493 }
21494}
21495
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021496sub printReport()
21497{
21498 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021499 createReport();
21500 if($JoinReport or $DoubleReport)
21501 {
21502 if($RESULT{"Binary"}{"Problems"}
21503 or $RESULT{"Source"}{"Problems"}) {
21504 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021505 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021506 else {
21507 printMsg("INFO", "result: COMPATIBLE");
21508 }
21509 printStatMsg("Binary");
21510 printStatMsg("Source");
21511 if($ListAffected)
21512 { # --list-affected
21513 listAffected("Binary");
21514 listAffected("Source");
21515 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021516 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021517 elsif($BinaryOnly)
21518 {
21519 if($RESULT{"Binary"}{"Problems"}) {
21520 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21521 }
21522 else {
21523 printMsg("INFO", "result: COMPATIBLE");
21524 }
21525 printStatMsg("Binary");
21526 if($ListAffected)
21527 { # --list-affected
21528 listAffected("Binary");
21529 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021530 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021531 elsif($SourceOnly)
21532 {
21533 if($RESULT{"Source"}{"Problems"}) {
21534 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21535 }
21536 else {
21537 printMsg("INFO", "result: COMPATIBLE");
21538 }
21539 printStatMsg("Source");
21540 if($ListAffected)
21541 { # --list-affected
21542 listAffected("Source");
21543 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021544 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021545 if($StdOut)
21546 {
21547 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021548 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021549 printMsg("INFO", "compatibility report has been generated to stdout");
21550 }
21551 else
21552 { # default
21553 printMsg("INFO", "compatibility reports have been generated to stdout");
21554 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021555 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021556 else
21557 {
21558 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021559 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021560 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21561 }
21562 elsif($DoubleReport)
21563 { # default
21564 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21565 }
21566 elsif($BinaryOnly)
21567 { # --binary
21568 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21569 }
21570 elsif($SourceOnly)
21571 { # --source
21572 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21573 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021574 }
21575}
21576
21577sub check_win32_env()
21578{
21579 if(not $ENV{"DevEnvDir"}
21580 or not $ENV{"LIB"}) {
21581 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21582 }
21583}
21584
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021585sub diffSets($$)
21586{
21587 my ($S1, $S2) = @_;
21588 my @SK1 = keys(%{$S1});
21589 my @SK2 = keys(%{$S2});
21590 if($#SK1!=$#SK2) {
21591 return 1;
21592 }
21593 foreach my $K1 (@SK1)
21594 {
21595 if(not defined $S2->{$K1}) {
21596 return 1;
21597 }
21598 }
21599 return 0;
21600}
21601
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021602sub defaultDumpPath($$)
21603{
21604 my ($N, $V) = @_;
21605 return "abi_dumps/".$N."/".$N."_".$V.".abi.".$AR_EXT; # gzipped by default
21606}
21607
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021608sub create_ABI_Dump()
21609{
21610 if(not -e $DumpAPI) {
21611 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21612 }
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021613
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021614 if(isDump($DumpAPI)) {
21615 read_ABI_Dump(1, $DumpAPI);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021616 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021617 else {
21618 readDescriptor(1, createDescriptor(1, $DumpAPI));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021619 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021620
21621 if(not $Descriptor{1}{"Version"})
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021622 { # set to default: N
21623 $Descriptor{1}{"Version"} = "N";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021624 }
21625
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021626 initLogging(1);
21627 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021628
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040021629 my $DumpPath = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021630 if($OutputDumpPath)
21631 { # user defined path
21632 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021633 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021634 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21635
21636 if(not $Archive and not $StdOut)
21637 { # check archive utilities
21638 if($OSgroup eq "windows")
21639 { # using zip
21640 my $ZipCmd = get_CmdPath("zip");
21641 if(not $ZipCmd) {
21642 exitStatus("Not_Found", "can't find \"zip\"");
21643 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021644 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021645 else
21646 { # using tar and gzip
21647 my $TarCmd = get_CmdPath("tar");
21648 if(not $TarCmd) {
21649 exitStatus("Not_Found", "can't find \"tar\"");
21650 }
21651 my $GzipCmd = get_CmdPath("gzip");
21652 if(not $GzipCmd) {
21653 exitStatus("Not_Found", "can't find \"gzip\"");
21654 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021655 }
21656 }
21657
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021658 if(not $Descriptor{1}{"Dump"})
21659 {
21660 if(not $CheckHeadersOnly) {
21661 readLibs(1);
21662 }
21663 if($CheckHeadersOnly) {
21664 setLanguage(1, "C++");
21665 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021666 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040021667 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021668 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021669 if(not $Descriptor{1}{"Dump"})
21670 {
21671 if($Descriptor{1}{"Headers"}) {
21672 readHeaders(1);
21673 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021674 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021675 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021676 if(not keys(%{$SymbolInfo{1}}))
21677 { # check if created dump is valid
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021678 if(not $ExtendedCheck)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021679 {
21680 if($CheckHeadersOnly) {
21681 exitStatus("Empty_Set", "the set of public symbols is empty");
21682 }
21683 else {
21684 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21685 }
21686 }
21687 }
21688 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021689 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021690 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21691 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021692 if($ExtraDump)
21693 { # add unmangled names to the ABI dump
21694 my @Names = ();
21695 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21696 {
21697 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21698 push(@Names, $MnglName);
21699 }
21700 }
21701 translateSymbols(@Names, 1);
21702 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21703 {
21704 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21705 {
21706 if(my $Unmangled = $tr_name{$MnglName})
21707 {
21708 if($MnglName ne $Unmangled) {
21709 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21710 }
21711 }
21712 }
21713 }
21714 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021715
21716 my %GccConstants = (); # built-in GCC constants
21717 foreach my $Name (keys(%{$Constants{1}}))
21718 {
21719 if(not defined $Constants{1}{$Name}{"Header"})
21720 {
21721 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21722 delete($Constants{1}{$Name});
21723 }
21724 }
21725
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021726 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021727 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021728 "TypeInfo" => $TypeInfo{1},
21729 "SymbolInfo" => $SymbolInfo{1},
21730 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021731 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021732 "SymbolVersion" => $SymVer{1},
21733 "LibraryVersion" => $Descriptor{1}{"Version"},
21734 "LibraryName" => $TargetLibraryName,
21735 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021736 "SkipTypes" => $SkipTypes{1},
21737 "SkipSymbols" => $SkipSymbols{1},
21738 "SkipNameSpaces" => $SkipNameSpaces{1},
21739 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021740 "Headers" => \%HeadersInfo,
21741 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021742 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021743 "NameSpaces" => $NestedNameSpaces{1},
21744 "Target" => $OStarget,
21745 "Arch" => getArch(1),
21746 "WordSize" => $WORD_SIZE{1},
21747 "GccVersion" => get_dumpversion($GCC_PATH),
21748 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21749 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21750 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021751 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021752 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021753 }
21754 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021755 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021756 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021757 if($ExtendedCheck)
21758 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021759 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021760 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021761 if($BinaryOnly)
21762 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021763 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021764 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021765 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021766 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021767 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021768 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21769 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021770 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021771
21772 my $ABI_DUMP = "";
21773 if($UseXML)
21774 {
21775 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021776 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021777 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021778 else
21779 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021780 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021781 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021782 if($StdOut)
21783 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021784 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021785 printMsg("INFO", "ABI dump has been generated to stdout");
21786 return;
21787 }
21788 else
21789 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021790 my ($DDir, $DName) = separate_path($DumpPath);
21791 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021792 if(not $Archive) {
21793 $DPath = $DumpPath;
21794 }
21795
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021796 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021797
21798 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021799 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021800 close(DUMP);
21801
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021802 if(not -s $DPath) {
21803 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21804 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021805 if($Archive) {
21806 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021807 }
21808
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021809 if($OutputDumpPath) {
21810 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021811 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021812 else {
21813 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
21814 }
21815 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 +040021816 }
21817}
21818
21819sub quickEmptyReports()
21820{ # Quick "empty" reports
21821 # 4 times faster than merging equal dumps
21822 # NOTE: the dump contains the "LibraryVersion" attribute
21823 # if you change the version, then your dump will be different
21824 # OVERCOME: use -v1 and v2 options for comparing dumps
21825 # and don't change version in the XML descriptor (and dumps)
21826 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
21827 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
21828 {
21829 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
21830 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
21831 if($FilePath1 and $FilePath2)
21832 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021833 my $Line = readLineNum($FilePath1, 0);
21834 if($Line=~/xml/)
21835 { # XML format
21836 # is not supported yet
21837 return;
21838 }
21839
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021840 local $/ = undef;
21841
21842 open(DUMP1, $FilePath1);
21843 my $Content1 = <DUMP1>;
21844 close(DUMP1);
21845
21846 open(DUMP2, $FilePath2);
21847 my $Content2 = <DUMP2>;
21848 close(DUMP2);
21849
21850 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021851 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021852 # clean memory
21853 undef $Content2;
21854
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021855 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021856 my $ABIdump = eval($Content1);
21857
21858 # clean memory
21859 undef $Content1;
21860
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021861 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021862 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 +040021863 }
21864 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021865 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021866 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
21867 }
21868 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021869 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021870 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
21871 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021872 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021873 read_Libs_DumpInfo($ABIdump, 1);
21874 read_Machine_DumpInfo($ABIdump, 1);
21875 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021876
21877 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
21878 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
21879
21880 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
21881 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
21882
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021883 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
21884 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
21885 exitReport();
21886 }
21887 }
21888 }
21889}
21890
21891sub initLogging($)
21892{
21893 my $LibVersion = $_[0];
21894 # create log directory
21895 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
21896 if($OutputLogPath{$LibVersion})
21897 { # user-defined by -log-path option
21898 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
21899 }
21900 if($LogMode ne "n") {
21901 mkpath($LOG_DIR);
21902 }
21903 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021904 if($Debug)
21905 { # debug directory
21906 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021907
21908 if(not $ExtraInfo)
21909 { # enable --extra-info
21910 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
21911 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021912 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021913 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021914}
21915
21916sub writeLog($$)
21917{
21918 my ($LibVersion, $Msg) = @_;
21919 if($LogMode ne "n") {
21920 appendFile($LOG_PATH{$LibVersion}, $Msg);
21921 }
21922}
21923
21924sub resetLogging($)
21925{
21926 my $LibVersion = $_[0];
21927 if($LogMode!~/a|n/)
21928 { # remove old log
21929 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021930 if($Debug) {
21931 rmtree($DEBUG_PATH{$LibVersion});
21932 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021933 }
21934}
21935
21936sub printErrorLog($)
21937{
21938 my $LibVersion = $_[0];
21939 if($LogMode ne "n") {
21940 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
21941 }
21942}
21943
21944sub isDump($)
21945{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021946 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz(\.\w+|)|\.zip|\.xml|)\Z/)
21947 { # NOTE: name.abi.tar.gz.amd64 (dh & cdbs)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021948 return $1;
21949 }
21950 return 0;
21951}
21952
21953sub isDump_U($)
21954{
Andrey Ponomarenkob9ed4c92014-04-16 13:53:17 +040021955 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021956 return $1;
21957 }
21958 return 0;
21959}
21960
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021961sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021962{
21963 # read input XML descriptors or ABI dumps
21964 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021965 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021966 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021967 if(not -e $Descriptor{1}{"Path"}) {
21968 exitStatus("Access_Error", "can't access \'".$Descriptor{1}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021969 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021970
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021971 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021972 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021973 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021974 if(not -e $Descriptor{2}{"Path"}) {
21975 exitStatus("Access_Error", "can't access \'".$Descriptor{2}{"Path"}."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021976 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021977
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021978 detect_default_paths("bin"); # to extract dumps
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021979 if(isDump($Descriptor{1}{"Path"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021980 and isDump($Descriptor{2}{"Path"}))
21981 { # optimization: equal ABI dumps
21982 quickEmptyReports();
21983 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021984
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021985 printMsg("INFO", "preparation, please wait ...");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021986
21987 if(isDump($Descriptor{1}{"Path"})) {
21988 read_ABI_Dump(1, $Descriptor{1}{"Path"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021989 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030021990 else {
21991 readDescriptor(1, createDescriptor(1, $Descriptor{1}{"Path"}));
21992 }
21993
21994 if(isDump($Descriptor{2}{"Path"})) {
21995 read_ABI_Dump(2, $Descriptor{2}{"Path"});
21996 }
21997 else {
21998 readDescriptor(2, createDescriptor(2, $Descriptor{2}{"Path"}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021999 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022000
22001 if(not $Descriptor{1}{"Version"})
22002 { # set to default: X
22003 $Descriptor{1}{"Version"} = "X";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022004 print STDERR "WARNING: version number #1 is not set (use --v1=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022005 }
22006
22007 if(not $Descriptor{2}{"Version"})
22008 { # set to default: Y
22009 $Descriptor{2}{"Version"} = "Y";
Andrey Ponomarenko15bfdc22015-09-20 13:21:01 +030022010 print STDERR "WARNING: version number #2 is not set (use --v2=NUM option)\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022011 }
22012
Andrey Ponomarenko2c530f72015-10-15 01:07:53 +030022013 if(not $UsedDump{1}{"V"}) {
22014 initLogging(1);
22015 }
22016
22017 if(not $UsedDump{2}{"V"}) {
22018 initLogging(2);
22019 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022020
22021 # check input data
22022 if(not $Descriptor{1}{"Headers"}) {
22023 exitStatus("Error", "can't find header files info in descriptor d1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022024 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022025 if(not $Descriptor{2}{"Headers"}) {
22026 exitStatus("Error", "can't find header files info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022027 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022028
22029 if(not $CheckHeadersOnly)
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022030 {
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022031 if(not $Descriptor{1}{"Libs"}) {
22032 exitStatus("Error", "can't find libraries info in descriptor d1");
22033 }
22034 if(not $Descriptor{2}{"Libs"}) {
22035 exitStatus("Error", "can't find libraries info in descriptor d2");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022036 }
22037 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022038
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022039 if($UseDumps)
22040 { # --use-dumps
22041 # parallel processing
Andrey Ponomarenko6bdaa962014-04-22 11:16:21 +040022042 my $DumpPath1 = defaultDumpPath($TargetLibraryName, $Descriptor{1}{"Version"});
22043 my $DumpPath2 = defaultDumpPath($TargetLibraryName, $Descriptor{2}{"Version"});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022044
22045 unlink($DumpPath1);
22046 unlink($DumpPath2);
22047
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022048 my $pid = fork();
22049 if($pid)
22050 { # dump on two CPU cores
22051 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22052 if($RelativeDirectory{1}) {
22053 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22054 }
22055 if($OutputLogPath{1}) {
22056 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22057 }
22058 if($CrossGcc) {
22059 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22060 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022061 if($Quiet)
22062 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022063 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022064 @PARAMS = (@PARAMS, "-logging-mode", "a");
22065 }
22066 elsif($LogMode and $LogMode ne "w")
22067 { # "w" is default
22068 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022069 }
22070 if($ExtendedCheck) {
22071 @PARAMS = (@PARAMS, "-extended");
22072 }
22073 if($UserLang) {
22074 @PARAMS = (@PARAMS, "-lang", $UserLang);
22075 }
22076 if($TargetVersion{1}) {
22077 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22078 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022079 if($BinaryOnly) {
22080 @PARAMS = (@PARAMS, "-binary");
22081 }
22082 if($SourceOnly) {
22083 @PARAMS = (@PARAMS, "-source");
22084 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022085 if($SortDump) {
22086 @PARAMS = (@PARAMS, "-sort");
22087 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022088 if($DumpFormat and $DumpFormat ne "perl") {
22089 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22090 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022091 if($CheckHeadersOnly) {
22092 @PARAMS = (@PARAMS, "-headers-only");
22093 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022094 if($Debug)
22095 {
22096 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022097 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022098 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022099 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022100 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022101 exit(1);
22102 }
22103 }
22104 else
22105 { # child
22106 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22107 if($RelativeDirectory{2}) {
22108 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22109 }
22110 if($OutputLogPath{2}) {
22111 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22112 }
22113 if($CrossGcc) {
22114 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22115 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022116 if($Quiet)
22117 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022118 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022119 @PARAMS = (@PARAMS, "-logging-mode", "a");
22120 }
22121 elsif($LogMode and $LogMode ne "w")
22122 { # "w" is default
22123 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022124 }
22125 if($ExtendedCheck) {
22126 @PARAMS = (@PARAMS, "-extended");
22127 }
22128 if($UserLang) {
22129 @PARAMS = (@PARAMS, "-lang", $UserLang);
22130 }
22131 if($TargetVersion{2}) {
22132 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22133 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022134 if($BinaryOnly) {
22135 @PARAMS = (@PARAMS, "-binary");
22136 }
22137 if($SourceOnly) {
22138 @PARAMS = (@PARAMS, "-source");
22139 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022140 if($SortDump) {
22141 @PARAMS = (@PARAMS, "-sort");
22142 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022143 if($DumpFormat and $DumpFormat ne "perl") {
22144 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22145 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022146 if($CheckHeadersOnly) {
22147 @PARAMS = (@PARAMS, "-headers-only");
22148 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022149 if($Debug)
22150 {
22151 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022152 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022153 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022154 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022155 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022156 exit(1);
22157 }
22158 else {
22159 exit(0);
22160 }
22161 }
22162 waitpid($pid, 0);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022163
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022164 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022165 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22166 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022167 if($TargetTitle ne $TargetLibraryName) {
22168 @CMP_PARAMS = (@CMP_PARAMS, "-title", $TargetTitle);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022169 }
22170 if($ShowRetVal) {
22171 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22172 }
22173 if($CrossGcc) {
22174 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22175 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022176 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22177 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022178 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022179 }
22180 if($ReportFormat and $ReportFormat ne "html")
22181 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022182 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22183 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022184 if($OutputReportPath) {
22185 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22186 }
22187 if($BinaryReportPath) {
22188 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22189 }
22190 if($SourceReportPath) {
22191 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22192 }
22193 if($LoggingPath) {
22194 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22195 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022196 if($CheckHeadersOnly) {
22197 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22198 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022199 if($BinaryOnly) {
22200 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22201 }
22202 if($SourceOnly) {
22203 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22204 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022205 if($Debug)
22206 {
22207 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22208 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022209 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022210 system("perl", $0, @CMP_PARAMS);
22211 exit($?>>8);
22212 }
22213 if(not $Descriptor{1}{"Dump"}
22214 or not $Descriptor{2}{"Dump"})
22215 { # need GCC toolchain to analyze
22216 # header files and libraries
22217 detect_default_paths("inc|lib|gcc");
22218 }
22219 if(not $Descriptor{1}{"Dump"})
22220 {
22221 if(not $CheckHeadersOnly) {
22222 readLibs(1);
22223 }
22224 if($CheckHeadersOnly) {
22225 setLanguage(1, "C++");
22226 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022227 searchForHeaders(1);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022228 $WORD_SIZE{1} = detectWordSize(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022229 }
22230 if(not $Descriptor{2}{"Dump"})
22231 {
22232 if(not $CheckHeadersOnly) {
22233 readLibs(2);
22234 }
22235 if($CheckHeadersOnly) {
22236 setLanguage(2, "C++");
22237 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022238 searchForHeaders(2);
Andrey Ponomarenko54040a12014-03-04 19:01:13 +040022239 $WORD_SIZE{2} = detectWordSize(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022240 }
22241 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22242 { # support for old ABI dumps
22243 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022244 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022245 {
22246 $WORD_SIZE{1} = $WORD_SIZE{2};
22247 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22248 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022249 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022250 {
22251 $WORD_SIZE{2} = $WORD_SIZE{1};
22252 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22253 }
22254 }
22255 elsif(not $WORD_SIZE{1}
22256 and not $WORD_SIZE{2})
22257 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022258 $WORD_SIZE{1} = "4";
22259 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022260 }
22261 if($Descriptor{1}{"Dump"})
22262 { # support for old ABI dumps
22263 prepareTypes(1);
22264 }
22265 if($Descriptor{2}{"Dump"})
22266 { # support for old ABI dumps
22267 prepareTypes(2);
22268 }
22269 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22270 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22271 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022272 # process input data
22273 if($Descriptor{1}{"Headers"}
22274 and not $Descriptor{1}{"Dump"}) {
22275 readHeaders(1);
22276 }
22277 if($Descriptor{2}{"Headers"}
22278 and not $Descriptor{2}{"Dump"}) {
22279 readHeaders(2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022280 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022281
22282 # clean memory
22283 %SystemHeaders = ();
22284 %mangled_name_gcc = ();
22285
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022286 prepareSymbols(1);
22287 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022288
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022289 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022290 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022291
22292 # Virtual Tables
22293 registerVTable(1);
22294 registerVTable(2);
22295
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022296 if(not checkDump(1, "1.22")
22297 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022298 { # support for old ABI dumps
22299 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22300 {
22301 if($ClassName=~/</)
22302 { # templates
22303 if(not defined $VirtualTable{1}{$ClassName})
22304 { # synchronize
22305 delete($VirtualTable{2}{$ClassName});
22306 }
22307 }
22308 }
22309 }
22310
22311 registerOverriding(1);
22312 registerOverriding(2);
22313
22314 setVirtFuncPositions(1);
22315 setVirtFuncPositions(2);
22316
22317 # Other
22318 addParamNames(1);
22319 addParamNames(2);
22320
22321 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022322}
22323
22324sub compareAPIs($)
22325{
22326 my $Level = $_[0];
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022327
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022328 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022329 loadModule("CallConv");
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022330
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022331 if($Level eq "Binary") {
22332 printMsg("INFO", "comparing ABIs ...");
22333 }
22334 else {
22335 printMsg("INFO", "comparing APIs ...");
22336 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022337
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022338 if($CheckHeadersOnly
22339 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022340 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022341 detectAdded_H($Level);
22342 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022343 }
22344 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022345 { # added/removed in libs
22346 detectAdded($Level);
22347 detectRemoved($Level);
22348 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022349
22350 mergeSymbols($Level);
22351 if(keys(%{$CheckedSymbols{$Level}})) {
22352 mergeConstants($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022353 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022354
22355 $Cache{"mergeTypes"} = (); # free memory
22356
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022357 if($CheckHeadersOnly
22358 or $Level eq "Source")
22359 { # added/removed in headers
22360 mergeHeaders($Level);
22361 }
22362 else
22363 { # added/removed in libs
22364 mergeLibs($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022365 }
22366}
22367
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022368sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022369{
22370 my %Opts = (
22371 "OStarget"=>$OStarget,
22372 "Debug"=>$Debug,
22373 "Quiet"=>$Quiet,
22374 "LogMode"=>$LogMode,
22375 "CheckHeadersOnly"=>$CheckHeadersOnly,
22376
22377 "SystemRoot"=>$SystemRoot,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022378 "GCC_PATH"=>$GCC_PATH,
22379 "TargetSysInfo"=>$TargetSysInfo,
22380 "CrossPrefix"=>$CrossPrefix,
22381 "TargetLibraryName"=>$TargetLibraryName,
22382 "CrossGcc"=>$CrossGcc,
22383 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022384 "NoStdInc"=>$NoStdInc,
22385
22386 "BinaryOnly" => $BinaryOnly,
22387 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022388 );
22389 return \%Opts;
22390}
22391
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022392sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022393{
22394 my %CODE_ERROR = reverse(%ERROR_CODE);
22395 return $CODE_ERROR{$_[0]};
22396}
22397
22398sub scenario()
22399{
22400 if($StdOut)
22401 { # enable quiet mode
22402 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022403 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022404 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022405 if(not $LogMode)
22406 { # default
22407 $LogMode = "w";
22408 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022409 if($UserLang)
22410 { # --lang=C++
22411 $UserLang = uc($UserLang);
22412 $COMMON_LANGUAGE{1}=$UserLang;
22413 $COMMON_LANGUAGE{2}=$UserLang;
22414 }
22415 if($LoggingPath)
22416 {
22417 $OutputLogPath{1} = $LoggingPath;
22418 $OutputLogPath{2} = $LoggingPath;
22419 if($Quiet) {
22420 $COMMON_LOG_PATH = $LoggingPath;
22421 }
22422 }
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022423
22424 if($SkipInternalSymbols) {
22425 $SkipInternalSymbols=~s/\*/.*/g;
22426 }
22427
22428 if($SkipInternalTypes) {
22429 $SkipInternalTypes=~s/\*/.*/g;
22430 }
22431
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022432 if($Quick) {
22433 $ADD_TMPL_INSTANCES = 0;
22434 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022435 if($OutputDumpPath)
22436 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022437 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022438 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22439 }
22440 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022441 if($BinaryOnly and $SourceOnly)
22442 { # both --binary and --source
22443 # is the default mode
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022444 if(not $CmpSystems)
22445 {
22446 $BinaryOnly = 0;
22447 $SourceOnly = 0;
22448 }
22449
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022450 $DoubleReport = 1;
22451 $JoinReport = 0;
Andrey Ponomarenko5e80d972015-09-01 19:42:01 +030022452
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022453 if($OutputReportPath)
22454 { # --report-path
22455 $DoubleReport = 0;
22456 $JoinReport = 1;
22457 }
22458 }
22459 elsif($BinaryOnly or $SourceOnly)
22460 { # --binary or --source
22461 $DoubleReport = 0;
22462 $JoinReport = 0;
22463 }
22464 if($UseXML)
22465 { # --xml option
22466 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022467 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022468 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022469 if($ReportFormat)
22470 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022471 $ReportFormat = lc($ReportFormat);
22472 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022473 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022474 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022475 if($ReportFormat eq "htm")
22476 { # HTM == HTML
22477 $ReportFormat = "html";
22478 }
22479 elsif($ReportFormat eq "xml")
22480 { # --report-format=XML equal to --xml
22481 $UseXML = 1;
22482 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022483 }
22484 else
22485 { # default: HTML
22486 $ReportFormat = "html";
22487 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022488 if($DumpFormat)
22489 { # validate
22490 $DumpFormat = lc($DumpFormat);
22491 if($DumpFormat!~/\A(xml|perl)\Z/) {
22492 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22493 }
22494 if($DumpFormat eq "xml")
22495 { # --dump-format=XML equal to --xml
22496 $UseXML = 1;
22497 }
22498 }
22499 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022500 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022501 $DumpFormat = "perl";
22502 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022503 if($Quiet and $LogMode!~/a|n/)
22504 { # --quiet log
22505 if(-f $COMMON_LOG_PATH) {
22506 unlink($COMMON_LOG_PATH);
22507 }
22508 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022509 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022510 $CheckUndefined = 1;
22511 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022512 if($TestTool and $UseDumps)
22513 { # --test && --use-dumps == --test-dump
22514 $TestDump = 1;
22515 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022516 if($Tolerant)
22517 { # enable all
22518 $Tolerance = 1234;
22519 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022520 if($Help)
22521 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022522 HELP_MESSAGE();
22523 exit(0);
22524 }
Andrey Ponomarenkoed4d3892015-08-14 14:18:21 +030022525 if($InfoMsg)
22526 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022527 INFO_MESSAGE();
22528 exit(0);
22529 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022530 if($ShowVersion)
22531 {
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022532 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 +040022533 exit(0);
22534 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022535 if($DumpVersion)
22536 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022537 printMsg("INFO", $TOOL_VERSION);
22538 exit(0);
22539 }
22540 if($ExtendedCheck) {
22541 $CheckHeadersOnly = 1;
22542 }
22543 if($SystemRoot_Opt)
22544 { # user defined root
22545 if(not -e $SystemRoot_Opt) {
22546 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22547 }
22548 $SystemRoot = $SystemRoot_Opt;
22549 $SystemRoot=~s/[\/]+\Z//g;
22550 if($SystemRoot) {
22551 $SystemRoot = get_abs_path($SystemRoot);
22552 }
22553 }
22554 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022555
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022556 if($SortDump)
22557 {
22558 $Data::Dumper::Useperl = 1;
22559 $Data::Dumper::Sortkeys = \&dump_sorting;
22560 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022561
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022562 if($TargetLibsPath)
22563 {
22564 if(not -f $TargetLibsPath) {
22565 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22566 }
22567 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22568 $TargetLibs{$Lib} = 1;
22569 }
22570 }
22571 if($TargetHeadersPath)
22572 { # --headers-list
22573 if(not -f $TargetHeadersPath) {
22574 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22575 }
22576 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22577 {
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022578 $TargetHeaders{1}{get_filename($Header)} = 1;
22579 $TargetHeaders{2}{get_filename($Header)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022580 }
22581 }
22582 if($TargetHeader)
22583 { # --header
Andrey Ponomarenko1fbbce62015-10-13 00:08:59 +030022584 $TargetHeaders{1}{get_filename($TargetHeader)} = 1;
22585 $TargetHeaders{2}{get_filename($TargetHeader)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022586 }
22587 if($TestTool
22588 or $TestDump)
22589 { # --test, --test-dump
22590 detect_default_paths("bin|gcc"); # to compile libs
22591 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022592 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022593 $LIB_EXT, $GCC_PATH, $SortDump, $CheckHeadersOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022594 exit(0);
22595 }
22596 if($DumpSystem)
22597 { # --dump-system
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022598
22599 if(not $TargetSysInfo) {
22600 exitStatus("Error", "-sysinfo option should be specified to dump system ABI");
22601 }
22602
22603 if(not -d $TargetSysInfo) {
22604 exitStatus("Access_Error", "can't access \'$TargetSysInfo\'");
22605 }
22606
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022607 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022608 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022609 { # system XML descriptor
22610 if(not -f $DumpSystem) {
22611 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22612 }
Andrey Ponomarenkoe32f7ea2015-08-26 16:20:23 +030022613
22614 my $SDesc = readFile($DumpSystem);
22615 if(my $RelDir = $RelativeDirectory{1}) {
22616 $SDesc =~ s/{RELPATH}/$RelDir/g;
22617 }
22618
22619 my $Ret = readSystemDescriptor($SDesc);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022620 foreach (@{$Ret->{"Tools"}})
22621 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022622 push_U($SystemPaths{"bin"}, $_);
22623 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022624 }
22625 if($Ret->{"CrossPrefix"}) {
22626 $CrossPrefix = $Ret->{"CrossPrefix"};
22627 }
22628 }
22629 elsif($SystemRoot_Opt)
22630 { # -sysroot "/" option
22631 # default target: /usr/lib, /usr/include
22632 # search libs: /usr/lib and /lib
22633 if(not -e $SystemRoot."/usr/lib") {
22634 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22635 }
22636 if(not -e $SystemRoot."/lib") {
22637 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22638 }
22639 if(not -e $SystemRoot."/usr/include") {
22640 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22641 }
22642 readSystemDescriptor("
22643 <name>
22644 $DumpSystem
22645 </name>
22646 <headers>
22647 $SystemRoot/usr/include
22648 </headers>
22649 <libs>
22650 $SystemRoot/usr/lib
22651 </libs>
22652 <search_libs>
22653 $SystemRoot/lib
22654 </search_libs>");
22655 }
22656 else {
22657 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22658 }
22659 detect_default_paths("bin|gcc"); # to check symbols
22660 if($OStarget eq "windows")
22661 { # to run dumpbin.exe
22662 # and undname.exe
22663 check_win32_env();
22664 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022665 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022666 exit(0);
22667 }
22668 if($CmpSystems)
22669 { # --cmp-systems
22670 detect_default_paths("bin"); # to extract dumps
22671 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022672 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022673 exit(0);
22674 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022675 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022676 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022677 }
22678 else
22679 { # validate library name
22680 if($TargetLibraryName=~/[\*\/\\]/) {
22681 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22682 }
22683 }
Andrey Ponomarenko14b8f022015-08-13 20:19:32 +030022684 if(not $TargetTitle) {
22685 $TargetTitle = $TargetLibraryName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022686 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022687
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022688 if($SymbolsListPath)
22689 {
22690 if(not -f $SymbolsListPath) {
22691 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22692 }
22693 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22694 $SymbolsList{$Interface} = 1;
22695 }
22696 }
Andrey Ponomarenko52b2e352015-08-11 22:45:36 +030022697 if($TypesListPath)
22698 {
22699 if(not -f $TypesListPath) {
22700 exitStatus("Access_Error", "can't access file \'$TypesListPath\'");
22701 }
22702 foreach my $Type (split(/\s*\n\s*/, readFile($TypesListPath))) {
22703 $TypesList{$Type} = 1;
22704 }
22705 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022706 if($SkipSymbolsListPath)
22707 {
22708 if(not -f $SkipSymbolsListPath) {
22709 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22710 }
Andrey Ponomarenkoa6d2e222015-09-12 22:45:07 +030022711 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath)))
22712 {
22713 $SkipSymbols{1}{$Interface} = 1;
22714 $SkipSymbols{2}{$Interface} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022715 }
22716 }
Andrey Ponomarenko99640d32015-11-01 21:20:50 +030022717 if($SkipTypesListPath)
22718 {
22719 if(not -f $SkipTypesListPath) {
22720 exitStatus("Access_Error", "can't access file \'$SkipTypesListPath\'");
22721 }
22722 foreach my $Type (split(/\s*\n\s*/, readFile($SkipTypesListPath)))
22723 {
22724 $SkipTypes{1}{$Type} = 1;
22725 $SkipTypes{2}{$Type} = 1;
22726 }
22727 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022728 if($SkipHeadersPath)
22729 {
22730 if(not -f $SkipHeadersPath) {
22731 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22732 }
22733 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022734 { # register for both versions
22735 $SkipHeadersList{1}{$Path} = 1;
22736 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022737 my ($CPath, $Type) = classifyPath($Path);
22738 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022739 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022740 }
22741 }
22742 if($ParamNamesPath)
22743 {
22744 if(not -f $ParamNamesPath) {
22745 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22746 }
22747 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22748 {
22749 if($Line=~s/\A(\w+)\;//)
22750 {
22751 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022752 if($Line=~/;(\d+);/)
22753 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022754 while($Line=~s/(\d+);(\w+)//) {
22755 $AddIntParams{$Interface}{$1}=$2;
22756 }
22757 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022758 else
22759 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022760 my $Num = 0;
22761 foreach my $Name (split(/;/, $Line)) {
22762 $AddIntParams{$Interface}{$Num++}=$Name;
22763 }
22764 }
22765 }
22766 }
22767 }
22768 if($AppPath)
22769 {
22770 if(not -f $AppPath) {
22771 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22772 }
Andrey Ponomarenkoced3a672015-08-26 15:56:27 +030022773
22774 detect_default_paths("bin|gcc");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022775 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022776 $SymbolsList_App{$Interface} = 1;
22777 }
22778 }
22779 if($DumpAPI)
22780 { # --dump-abi
22781 # make an API dump
22782 create_ABI_Dump();
22783 exit($COMPILE_ERRORS);
22784 }
22785 # default: compare APIs
22786 # -d1 <path>
22787 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022788 compareInit();
22789 if($JoinReport or $DoubleReport)
22790 {
22791 compareAPIs("Binary");
22792 compareAPIs("Source");
22793 }
22794 elsif($BinaryOnly) {
22795 compareAPIs("Binary");
22796 }
22797 elsif($SourceOnly) {
22798 compareAPIs("Source");
22799 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022800 exitReport();
22801}
22802
22803scenario();