blob: bd08cdd996a89653905f557152a8ff7a81f99cf1 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04003# ABI Compliance Checker (ACC) 1.99.9
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-2010 The Linux Foundation
7# Copyright (C) 2009-2011 Institute for System Programming, RAS
8# Copyright (C) 2011-2012 Nokia Corporation and/or its subsidiary(-ies)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04009# Copyright (C) 2011-2014 ROSA 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 Ponomarenkod5958082014-01-23 13:36:03 +040020# - G++ (3.0-4.7, 4.8.3, recommended 4.5 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 Ponomarenko989a50b2012-04-03 12:24:22 +040030# - MinGW (3.0-4.7, recommended 4.5 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 Ponomarenkof442c172013-07-30 19:08:11 +040041# ABI Dumper >= 0.98
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 Ponomarenkod5958082014-01-23 13:36:03 +040067my $TOOL_VERSION = "1.99.9";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040068my $ABI_DUMP_VERSION = "3.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040069my $OLDEST_SUPPORTED_VERSION = "1.18";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040070my $XML_REPORT_VERSION = "1.2";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040071my $XML_ABI_DUMP_VERSION = "1.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040072my $OSgroup = get_OSgroup();
73my $ORIG_DIR = cwd();
74my $TMP_DIR = tempdir(CLEANUP=>1);
75
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
84my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName, $GenerateTemplate,
85$TestTool, $DumpAPI, $SymbolsListPath, $CheckHeadersOnly_Opt, $UseDumps,
86$CheckObjectsOnly_Opt, $AppPath, $StrictCompat, $DumpVersion, $ParamNamesPath,
87%RelativeDirectory, $TargetLibraryFName, $TestDump, $CheckImpl, $LoggingPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040088%TargetVersion, $InfoMsg, $UseOldDumps, $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 Ponomarenko07aea072012-11-12 16:15:07 +040094$SourceReportPath, $UseXML, $Browse, $OpenReport, $SortDump, $DumpFormat,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040095$ExtraInfo, $ExtraDump, $Force, $Tolerance, $Tolerant, $SkipSymbolsListPath,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040096$CheckInfo, $Quick, $AffectLimit, $AllAffected, $CppIncompat, $SkipInternal);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040097
98my $CmdName = get_filename($0);
99my %OS_LibExt = (
100 "dynamic" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400101 "linux"=>"so",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400102 "macos"=>"dylib",
103 "windows"=>"dll",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400104 "symbian"=>"dso",
105 "default"=>"so"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400106 },
107 "static" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400108 "linux"=>"a",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400109 "windows"=>"lib",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400110 "symbian"=>"lib",
111 "default"=>"a"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400112 }
113);
114
115my %OS_Archive = (
116 "windows"=>"zip",
117 "default"=>"tar.gz"
118);
119
120my %ERROR_CODE = (
121 # Compatible verdict
122 "Compatible"=>0,
123 "Success"=>0,
124 # Incompatible verdict
125 "Incompatible"=>1,
126 # Undifferentiated error code
127 "Error"=>2,
128 # System command is not found
129 "Not_Found"=>3,
130 # Cannot access input files
131 "Access_Error"=>4,
132 # Cannot compile header files
133 "Cannot_Compile"=>5,
134 # Header compiled with errors
135 "Compile_Error"=>6,
136 # Invalid input ABI dump
137 "Invalid_Dump"=>7,
138 # Incompatible version of ABI dump
139 "Dump_Version"=>8,
140 # Cannot find a module
141 "Module_Error"=>9,
142 # Empty intersection between
143 # headers and shared objects
144 "Empty_Intersection"=>10,
145 # Empty set of symbols in headers
146 "Empty_Set"=>11
147);
148
149my %HomePage = (
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400150 "Wiki"=>"http://ispras.linuxbase.org/index.php/ABI_compliance_checker",
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400151 "Dev1"=>"https://github.com/lvc/abi-compliance-checker",
152 "Dev2"=>"http://forge.ispras.ru/projects/abi-compliance-checker"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400153);
154
155my $ShortUsage = "ABI Compliance Checker (ACC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400156A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400157Copyright (C) 2014 ROSA Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400158License: GNU LGPL or GNU GPL
159
160Usage: $CmdName [options]
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400161Example: $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400162
163OLD.xml and NEW.xml are XML-descriptors:
164
165 <version>
166 1.0
167 </version>
168
169 <headers>
170 /path/to/headers/
171 </headers>
172
173 <libs>
174 /path/to/libraries/
175 </libs>
176
177More info: $CmdName --help\n";
178
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400179if($#ARGV==-1)
180{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400181 printMsg("INFO", $ShortUsage);
182 exit(0);
183}
184
185foreach (2 .. $#ARGV)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400186{ # correct comma separated options
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400187 if($ARGV[$_-1] eq ",")
188 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400189 $ARGV[$_-2].=",".$ARGV[$_];
190 splice(@ARGV, $_-1, 2);
191 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400192 elsif($ARGV[$_-1]=~/,\Z/)
193 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400194 $ARGV[$_-1].=$ARGV[$_];
195 splice(@ARGV, $_, 1);
196 }
197 elsif($ARGV[$_]=~/\A,/
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400198 and $ARGV[$_] ne ",")
199 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400200 $ARGV[$_-1].=$ARGV[$_];
201 splice(@ARGV, $_, 1);
202 }
203}
204
205GetOptions("h|help!" => \$Help,
206 "i|info!" => \$InfoMsg,
207 "v|version!" => \$ShowVersion,
208 "dumpversion!" => \$DumpVersion,
209# general options
210 "l|lib|library=s" => \$TargetLibraryName,
211 "d1|old|o=s" => \$Descriptor{1}{"Path"},
212 "d2|new|n=s" => \$Descriptor{2}{"Path"},
213 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
214 "old-dumps!" => \$UseOldDumps,
215# extra options
216 "d|descriptor-template!" => \$GenerateTemplate,
217 "app|application=s" => \$AppPath,
218 "static-libs!" => \$UseStaticLibs,
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +0400219 "cross-gcc|gcc-path=s" => \$CrossGcc,
220 "cross-prefix|gcc-prefix=s" => \$CrossPrefix,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400221 "sysroot=s" => \$SystemRoot_Opt,
222 "v1|version1|vnum=s" => \$TargetVersion{1},
223 "v2|version2=s" => \$TargetVersion{2},
224 "s|strict!" => \$StrictCompat,
225 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400226 "skip-symbols=s" => \$SkipSymbolsListPath,
227 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400228 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400229 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400230 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
231 "objects-only!" => \$CheckObjectsOnly_Opt,
232 "check-impl|check-implementation!" => \$CheckImpl,
233 "show-retval!" => \$ShowRetVal,
234 "use-dumps!" => \$UseDumps,
235 "nostdinc!" => \$NoStdInc,
236 "dump-system=s" => \$DumpSystem,
237 "sysinfo=s" => \$TargetSysInfo,
238 "cmp-systems!" => \$CmpSystems,
239 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400240 "ext|extended!" => \$ExtendedCheck,
241 "q|quiet!" => \$Quiet,
242 "stdout!" => \$StdOut,
243 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400244 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400245 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400246 "lang=s" => \$UserLang,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400247 "binary|bin|abi!" => \$BinaryOnly,
248 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400249 "limit-affected|affected-limit=s" => \$AffectLimit,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400250# other options
251 "test!" => \$TestTool,
252 "test-dump!" => \$TestDump,
253 "debug!" => \$Debug,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400254 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400255 "cpp-incompatible!" => \$CppIncompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400256 "p|params=s" => \$ParamNamesPath,
257 "relpath1|relpath=s" => \$RelativeDirectory{1},
258 "relpath2=s" => \$RelativeDirectory{2},
259 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400260 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400261 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400262 "bin-report-path=s" => \$BinaryReportPath,
263 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400264 "log-path=s" => \$LoggingPath,
265 "log1-path=s" => \$OutputLogPath{1},
266 "log2-path=s" => \$OutputLogPath{2},
267 "logging-mode=s" => \$LogMode,
268 "list-affected!" => \$ListAffected,
269 "l-full|lib-full=s" => \$TargetLibraryFName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400270 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400271 "b|browse=s" => \$Browse,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400272 "open!" => \$OpenReport,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400273 "extra-info=s" => \$ExtraInfo,
274 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400275 "force!" => \$Force,
276 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400277 "tolerant!" => \$Tolerant,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400278 "check!" => \$CheckInfo,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400279 "quick!" => \$Quick,
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400280 "all-affected!" => \$AllAffected,
281 "skip-internal=s" => \$SkipInternal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400282) or ERR_MESSAGE();
283
284sub ERR_MESSAGE()
285{
286 printMsg("INFO", "\n".$ShortUsage);
287 exit($ERROR_CODE{"Error"});
288}
289
290my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
291my $SLIB_TYPE = $LIB_TYPE;
292if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
293{ # show as "shared" library
294 $SLIB_TYPE = "shared";
295}
296my $LIB_EXT = getLIB_EXT($OSgroup);
297my $AR_EXT = getAR_EXT($OSgroup);
298my $BYTE_SIZE = 8;
299my $COMMON_LOG_PATH = "logs/run.log";
300
301my $HelpMessage="
302NAME:
303 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400304 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400305
306DESCRIPTION:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400307 ABI Compliance Checker (ACC) is a tool for checking backward binary and
308 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
309 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
310 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
311 and/or source-level compatibility: changes in calling stack, v-table changes,
312 removed symbols, renamed fields, etc. Binary incompatibility may result in
313 crashing or incorrect behavior of applications built with an old version of
314 a library if they run on a new one. Source incompatibility may result in
315 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400316
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400317 The tool is intended for developers of software libraries and maintainers
318 of operating systems who are interested in ensuring backward compatibility,
319 i.e. allow old applications to run or to be recompiled with newer library
320 versions.
321
322 Also the tool can be used by ISVs for checking applications portability to
323 new library versions. Found issues can be taken into account when adapting
324 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400325
326 This tool is free software: you can redistribute it and/or modify it
327 under the terms of the GNU LGPL or GNU GPL.
328
329USAGE:
330 $CmdName [options]
331
332EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400333 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400334
335 OLD.xml and NEW.xml are XML-descriptors:
336
337 <version>
338 1.0
339 </version>
340
341 <headers>
342 /path1/to/header(s)/
343 /path2/to/header(s)/
344 ...
345 </headers>
346
347 <libs>
348 /path1/to/library(ies)/
349 /path2/to/library(ies)/
350 ...
351 </libs>
352
353INFORMATION OPTIONS:
354 -h|-help
355 Print this help.
356
357 -i|-info
358 Print complete info.
359
360 -v|-version
361 Print version information.
362
363 -dumpversion
364 Print the tool version ($TOOL_VERSION) and don't do anything else.
365
366GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400367 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400368 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400369
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400370 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400371 Descriptor of 1st (old) library version.
372 It may be one of the following:
373
374 1. XML-descriptor (VERSION.xml file):
375
376 <version>
377 1.0
378 </version>
379
380 <headers>
381 /path1/to/header(s)/
382 /path2/to/header(s)/
383 ...
384 </headers>
385
386 <libs>
387 /path1/to/library(ies)/
388 /path2/to/library(ies)/
389 ...
390 </libs>
391
392 ... (XML-descriptor template
393 can be generated by -d option)
394
395 2. ABI dump generated by -dump option
396 3. Directory with headers and/or $SLIB_TYPE libraries
397 4. Single header file
398 5. Single $SLIB_TYPE library
399 6. Comma separated list of headers and/or libraries
400
401 If you are using an 2-6 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400402 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400403
404 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400405 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400406
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400407 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400408 Descriptor of 2nd (new) library version.
409
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400410 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400411 Create library ABI dump for the input XML descriptor. You can
412 transfer it anywhere and pass instead of the descriptor. Also
413 it can be used for debugging the tool.
414
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400415 Supported ABI dump versions: 2.0<=V<=$ABI_DUMP_VERSION
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400416
417 -old-dumps
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400418 Enable support for old-version ABI dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0).\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400419
420sub HELP_MESSAGE() {
421 printMsg("INFO", $HelpMessage."
422MORE INFO:
423 $CmdName --info\n");
424}
425
426sub INFO_MESSAGE()
427{
428 printMsg("INFO", "$HelpMessage
429EXTRA OPTIONS:
430 -d|-descriptor-template
431 Create XML-descriptor template ./VERSION.xml
432
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400433 -app|-application PATH
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200434 This option allows one to specify the application that should be checked
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400435 for portability to the new library version.
436
437 -static-libs
438 Check static libraries instead of the shared ones. The <libs> section
439 of the XML-descriptor should point to static libraries location.
440
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400441 -cross-gcc|-gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400442 Path to the cross GCC compiler to use instead of the usual (host) GCC.
443
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400444 -cross-prefix|-gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400445 GCC toolchain prefix.
446
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400447 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400448 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400449 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400450
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400451 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400452 Specify 1st library version outside the descriptor. This option is needed
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200453 if you have preferred an alternative descriptor type (see -d1 option).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400454
455 In general case you should specify it in the XML-descriptor:
456 <version>
457 VERSION
458 </version>
459
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400460 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400461 Specify 2nd library version outside the descriptor.
462
463 -s|-strict
464 Treat all compatibility warnings as problems. Add a number of \"Low\"
465 severity problems to the return value of the tool.
466
467 -headers-only
468 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
469 provide a low quality compatibility report with false positives and
470 without detecting of added/removed symbols.
471
472 Alternatively you can write \"none\" word to the <libs> section
473 in the XML-descriptor:
474 <libs>
475 none
476 </libs>
477
478 -objects-only
479 Check $SLIB_TYPE libraries without header files. It is easy to run, but may
480 provide a low quality compatibility report with false positives and
481 without analysis of changes in parameters and data types.
482
483 Alternatively you can write \"none\" word to the <headers> section
484 in the XML-descriptor:
485 <headers>
486 none
487 </headers>
488
489 -check-impl|-check-implementation
490 Compare canonified disassembled binary code of $SLIB_TYPE libraries to
491 detect changes in the implementation. Add \'Problems with Implementation\'
492 section to the report.
493
494 -show-retval
495 Show the symbol's return type in the report.
496
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400497 -symbols-list PATH
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200498 This option allows one to specify a file with a list of symbols (mangled
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400499 names in C++) that should be checked, other symbols will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400500
501 -skip-symbols PATH
502 The list of symbols that should NOT be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400503
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400504 -headers-list PATH
505 The file with a list of headers, that should be checked/dumped.
506
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400507 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400508 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400509
510 -header NAME
511 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400512
513 -use-dumps
514 Make dumps for two versions of a library and compare dumps. This should
515 increase the performance of the tool and decrease the system memory usage.
516
517 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400518 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400519
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400520 -dump-system NAME -sysroot DIR
521 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400522 create XML descriptors and make ABI dumps for each library. The result
523 set of ABI dumps can be compared (--cmp-systems) with the other one
524 created for other version of operating system in order to check them for
525 compatibility. Do not forget to specify -cross-gcc option if your target
526 system requires some specific version of GCC compiler (different from
527 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400528 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400529
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400530 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400531 The same as the previous option but takes an XML descriptor of the target
532 system as input, where you should describe it:
533
534 /* Primary sections */
535
536 <name>
537 /* Name of the system */
538 </name>
539
540 <headers>
541 /* The list of paths to header files and/or
542 directories with header files, one per line */
543 </headers>
544
545 <libs>
546 /* The list of paths to shared libraries and/or
547 directories with shared libraries, one per line */
548 </libs>
549
550 /* Optional sections */
551
552 <search_headers>
553 /* List of directories to be searched
554 for header files to automatically
555 generate include paths, one per line */
556 </search_headers>
557
558 <search_libs>
559 /* List of directories to be searched
560 for shared libraries to resolve
561 dependencies, one per line */
562 </search_libs>
563
564 <tools>
565 /* List of directories with tools used
566 for analysis (GCC toolchain), one per line */
567 </tools>
568
569 <cross_prefix>
570 /* GCC toolchain prefix.
571 Examples:
572 arm-linux-gnueabi
573 arm-none-symbianelf */
574 </cross_prefix>
575
576 <gcc_options>
577 /* Additional GCC options, one per line */
578 </gcc_options>
579
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400580 -sysinfo DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400581 This option may be used with -dump-system to dump ABI of operating
582 systems and configure the dumping process.
583 Default:
584 modules/Targets/{unix, symbian, windows}
585
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400586 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400587 Compare two system ABI dumps. Create compatibility reports for each
588 library and the common HTML report including the summary of test
589 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400590 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400591
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400592 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400593 The file with a list of libraries, that should be dumped by
594 the -dump-system option or should be checked by the -cmp-systems option.
595
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400596 -ext|-extended
597 If your library A is supposed to be used by other library B and you
598 want to control the ABI of B, then you should enable this option. The
599 tool will check for changes in all data types, even if they are not
600 used by any function in the library A. Such data types are not part
601 of the A library ABI, but may be a part of the ABI of the B library.
602
603 The short scheme is:
604 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
605
606 -q|-quiet
607 Print all messages to the file instead of stdout and stderr.
608 Default path (can be changed by -log-path option):
609 $COMMON_LOG_PATH
610
611 -stdout
612 Print analysis results (compatibility reports and ABI dumps) to stdout
613 instead of creating a file. This would allow piping data to other programs.
614
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400615 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400616 Change format of compatibility report.
617 Formats:
618 htm - HTML format (default)
619 xml - XML format
620
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400621 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400622 Change format of ABI dump.
623 Formats:
624 perl - Data::Dumper format (default)
625 xml - XML format
626
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400627 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400628 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400629
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400630 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400631 Set library language (C or C++). You can use this option if the tool
632 cannot auto-detect a language. This option may be useful for checking
633 C-library headers (--lang=C) in --headers-only or --extended modes.
634
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400635 -binary|-bin|-abi
636 Show \"Binary\" compatibility problems only.
637 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400638 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400639
640 -source|-src|-api
641 Show \"Source\" compatibility problems only.
642 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400643 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400644
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +0400645 -limit-affected LIMIT
Andrey Ponomarenkof442c172013-07-30 19:08:11 +0400646 The maximum number of affected symbols listed under the description
647 of the changed type in the report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400648
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400649OTHER OPTIONS:
650 -test
651 Run internal tests. Create two binary incompatible versions of a sample
652 library and run the tool to check them for compatibility. This option
Mathieu Malaterrebd1767a2013-08-26 15:03:58 +0200653 allows one to check if the tool works correctly in the current environment.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400654
655 -test-dump
656 Test ability to create, read and compare ABI dumps.
657
658 -debug
659 Debugging mode. Print debug info on the screen. Save intermediate
660 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400661 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400662
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400663 Also consider using --dump option for debugging the tool.
664
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400665 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400666 If your header files are written in C language and can be compiled
667 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
668 the tool about this and speedup the analysis.
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +0400669
670 -cpp-incompatible
671 Set this option if input C header files use C++ keywords.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400672
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400673 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400674 Path to file with the function parameter names. It can be used
675 for improving report view if the library header files have no
676 parameter names. File format:
677
678 func1;param1;param2;param3 ...
679 func2;param1;param2;param3 ...
680 ...
681
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400682 -relpath PATH
683 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400684 for dumping the library ABI (see -dump option).
685
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400686 -relpath1 PATH
687 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400688
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400689 -relpath2 PATH
690 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400691
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400692 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400693 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400694 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400695 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400696
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400697 -sort
698 Enable sorting of data in ABI dumps.
699
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400700 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400701 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400702 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400703 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400704
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400705 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400706 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400707 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400708 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400709
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400710 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400711 Path to \"Source\" compatibility report.
712 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400713 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400714
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400715 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400716 Log path for all messages.
717 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400718 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400719
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400720 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400721 Log path for 1st version of a library.
722 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400723 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400724
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400725 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400726 Log path for 2nd version of a library.
727 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400728 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400729
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400730 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400731 Change logging mode.
732 Modes:
733 w - overwrite old logs (default)
734 a - append old logs
735 n - do not write any logs
736
737 -list-affected
738 Generate file with the list of incompatible
739 symbols beside the HTML compatibility report.
740 Use 'c++filt \@file' command from GNU binutils
741 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400742 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400743 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400744 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400745
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400746 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400747 The component name in the title and summary of the HTML report.
748 Default:
749 library
750
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400751 -l-full|-lib-full NAME
752 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400753 will be displayed a name specified by -l option.
754
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400755 -b|-browse PROGRAM
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400756 Open report(s) in the browser (firefox, opera, etc.).
757
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400758 -open
759 Open report(s) in the default browser.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400760
761 -extra-info DIR
762 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400763
764 -extra-dump
765 Create extended ABI dump containing all symbols
766 from the translation unit.
767
768 -force
769 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400770
771 -tolerance LEVEL
772 Apply a set of heuristics to successfully compile input
773 header files. You can enable several tolerance levels by
774 joining them into one string (e.g. 13, 124, etc.).
775 Levels:
776 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
777 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
778 3 - skip headers that iclude non-Linux headers
779 4 - skip headers included by others
780
781 -tolerant
782 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400783
784 -check
785 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400786
787 -quick
788 Quick analysis. Disable check of some template instances.
Andrey Ponomarenkod5958082014-01-23 13:36:03 +0400789
790 -skip-internal PATTERN
791 Do not check internal interfaces matched by the pattern.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400792
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400793REPORT:
794 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400795 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400796
797 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400798 logs/LIB_NAME/V1/log.txt
799 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400800
801EXIT CODES:
802 0 - Compatible. The tool has run without any errors.
803 non-zero - Incompatible or the tool has run with errors.
804
805REPORT BUGS TO:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400806 Andrey Ponomarenko <aponomarenko\@rosalab.ru>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400807
808MORE INFORMATION:
809 ".$HomePage{"Wiki"}."
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400810 ".$HomePage{"Dev1"}."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400811}
812
813my $DescriptorTemplate = "
814<?xml version=\"1.0\" encoding=\"utf-8\"?>
815<descriptor>
816
817/* Primary sections */
818
819<version>
820 /* Version of the library */
821</version>
822
823<headers>
824 /* The list of paths to header files and/or
825 directories with header files, one per line */
826</headers>
827
828<libs>
829 /* The list of paths to shared libraries (*.$LIB_EXT) and/or
830 directories with shared libraries, one per line */
831</libs>
832
833/* Optional sections */
834
835<include_paths>
836 /* The list of include paths that will be provided
837 to GCC to compile library headers, one per line.
838 NOTE: If you define this section then the tool
839 will not automatically generate include paths */
840</include_paths>
841
842<add_include_paths>
843 /* The list of include paths that will be added
844 to the automatically generated include paths, one per line */
845</add_include_paths>
846
847<skip_include_paths>
848 /* The list of include paths that will be removed from the
849 list of automatically generated include paths, one per line */
850</skip_include_paths>
851
852<gcc_options>
853 /* Additional GCC options, one per line */
854</gcc_options>
855
856<include_preamble>
857 /* The list of header files that will be
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +0400858 included before other headers, one per line */
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400859</include_preamble>
860
861<defines>
862 /* The list of defines that will be added at the
863 headers compiling stage, one per line:
864 #define A B
865 #define C D */
866</defines>
867
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +0400868<add_namespaces>
869 /* The list of namespaces that should be added to the alanysis
870 if the tool cannot find them automatically, one per line */
871</add_namespaces>
872
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400873<skip_types>
874 /* The list of data types, that
875 should not be checked, one per line */
876</skip_types>
877
878<skip_symbols>
879 /* The list of functions (mangled/symbol names in C++),
880 that should not be checked, one per line */
881</skip_symbols>
882
883<skip_namespaces>
884 /* The list of C++ namespaces, that
885 should not be checked, one per line */
886</skip_namespaces>
887
888<skip_constants>
889 /* The list of constants that should
890 not be checked, one name per line */
891</skip_constants>
892
893<skip_headers>
894 /* The list of header files and/or directories
895 with header files that should not be checked, one per line */
896</skip_headers>
897
898<skip_libs>
899 /* The list of shared libraries and/or directories
900 with shared libraries that should not be checked, one per line */
901</skip_libs>
902
903<skip_including>
904 /* The list of header files, that cannot be included
905 directly (or non-self compiled ones), one per line */
906</skip_including>
907
908<search_headers>
909 /* List of directories to be searched
910 for header files to automatically
911 generate include paths, one per line. */
912</search_headers>
913
914<search_libs>
915 /* List of directories to be searched
916 for shared librariess to resolve
917 dependencies, one per line */
918</search_libs>
919
920<tools>
921 /* List of directories with tools used
922 for analysis (GCC toolchain), one per line */
923</tools>
924
925<cross_prefix>
926 /* GCC toolchain prefix.
927 Examples:
928 arm-linux-gnueabi
929 arm-none-symbianelf */
930</cross_prefix>
931
932</descriptor>";
933
934my %Operator_Indication = (
935 "not" => "~",
936 "assign" => "=",
937 "andassign" => "&=",
938 "orassign" => "|=",
939 "xorassign" => "^=",
940 "or" => "|",
941 "xor" => "^",
942 "addr" => "&",
943 "and" => "&",
944 "lnot" => "!",
945 "eq" => "==",
946 "ne" => "!=",
947 "lt" => "<",
948 "lshift" => "<<",
949 "lshiftassign" => "<<=",
950 "rshiftassign" => ">>=",
951 "call" => "()",
952 "mod" => "%",
953 "modassign" => "%=",
954 "subs" => "[]",
955 "land" => "&&",
956 "lor" => "||",
957 "rshift" => ">>",
958 "ref" => "->",
959 "le" => "<=",
960 "deref" => "*",
961 "mult" => "*",
962 "preinc" => "++",
963 "delete" => " delete",
964 "vecnew" => " new[]",
965 "vecdelete" => " delete[]",
966 "predec" => "--",
967 "postinc" => "++",
968 "postdec" => "--",
969 "plusassign" => "+=",
970 "plus" => "+",
971 "minus" => "-",
972 "minusassign" => "-=",
973 "gt" => ">",
974 "ge" => ">=",
975 "new" => " new",
976 "multassign" => "*=",
977 "divassign" => "/=",
978 "div" => "/",
979 "neg" => "-",
980 "pos" => "+",
981 "memref" => "->*",
982 "compound" => "," );
983
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400984my %UnknownOperator;
985
986my %NodeType= (
987 "array_type" => "Array",
988 "binfo" => "Other",
989 "boolean_type" => "Intrinsic",
990 "complex_type" => "Intrinsic",
991 "const_decl" => "Other",
992 "enumeral_type" => "Enum",
993 "field_decl" => "Other",
994 "function_decl" => "Other",
995 "function_type" => "FunctionType",
996 "identifier_node" => "Other",
997 "integer_cst" => "Other",
998 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400999 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001000 "method_type" => "MethodType",
1001 "namespace_decl" => "Other",
1002 "parm_decl" => "Other",
1003 "pointer_type" => "Pointer",
1004 "real_cst" => "Other",
1005 "real_type" => "Intrinsic",
1006 "record_type" => "Struct",
1007 "reference_type" => "Ref",
1008 "string_cst" => "Other",
1009 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001010 "template_type_parm" => "TemplateParam",
1011 "typename_type" => "TypeName",
1012 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001013 "tree_list" => "Other",
1014 "tree_vec" => "Other",
1015 "type_decl" => "Other",
1016 "union_type" => "Union",
1017 "var_decl" => "Other",
1018 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001019 "nop_expr" => "Other", #
1020 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001021 "offset_type" => "Other" );
1022
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001023my %CppKeywords_C = map {$_=>1} (
1024 # C++ 2003 keywords
1025 "public",
1026 "protected",
1027 "private",
1028 "default",
1029 "template",
1030 "new",
1031 #"asm",
1032 "dynamic_cast",
1033 "auto",
1034 "try",
1035 "namespace",
1036 "typename",
1037 "using",
1038 "reinterpret_cast",
1039 "friend",
1040 "class",
1041 "virtual",
1042 "const_cast",
1043 "mutable",
1044 "static_cast",
1045 "export",
1046 # C++0x keywords
1047 "noexcept",
1048 "nullptr",
1049 "constexpr",
1050 "static_assert",
1051 "explicit",
1052 # cannot be used as a macro name
1053 # as it is an operator in C++
1054 "and",
1055 #"and_eq",
1056 "not",
1057 #"not_eq",
1058 "or"
1059 #"or_eq",
1060 #"bitand",
1061 #"bitor",
1062 #"xor",
1063 #"xor_eq",
1064 #"compl"
1065);
1066
1067my %CppKeywords_F = map {$_=>1} (
1068 "delete",
1069 "catch",
1070 "alignof",
1071 "thread_local",
1072 "decltype",
1073 "typeid"
1074);
1075
1076my %CppKeywords_O = map {$_=>1} (
1077 "bool",
1078 "register",
1079 "inline",
1080 "operator"
1081);
1082
1083my %CppKeywords_A = map {$_=>1} (
1084 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001085 "throw",
1086 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001087);
1088
1089foreach (keys(%CppKeywords_C),
1090keys(%CppKeywords_F),
1091keys(%CppKeywords_O)) {
1092 $CppKeywords_A{$_}=1;
1093}
1094
1095# Header file extensions as described by gcc
1096my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
1097
1098my %IntrinsicMangling = (
1099 "void" => "v",
1100 "bool" => "b",
1101 "wchar_t" => "w",
1102 "char" => "c",
1103 "signed char" => "a",
1104 "unsigned char" => "h",
1105 "short" => "s",
1106 "unsigned short" => "t",
1107 "int" => "i",
1108 "unsigned int" => "j",
1109 "long" => "l",
1110 "unsigned long" => "m",
1111 "long long" => "x",
1112 "__int64" => "x",
1113 "unsigned long long" => "y",
1114 "__int128" => "n",
1115 "unsigned __int128" => "o",
1116 "float" => "f",
1117 "double" => "d",
1118 "long double" => "e",
1119 "__float80" => "e",
1120 "__float128" => "g",
1121 "..." => "z"
1122);
1123
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001124my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
1125
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001126my %StdcxxMangling = (
1127 "3std"=>"St",
1128 "3std9allocator"=>"Sa",
1129 "3std12basic_string"=>"Sb",
1130 "3std12basic_stringIcE"=>"Ss",
1131 "3std13basic_istreamIcE"=>"Si",
1132 "3std13basic_ostreamIcE"=>"So",
1133 "3std14basic_iostreamIcE"=>"Sd"
1134);
1135
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04001136my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001137my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
1138
1139my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001140my $EMERGENCY_MODE_48 = 0;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001141
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001142my %ConstantSuffix = (
1143 "unsigned int"=>"u",
1144 "long"=>"l",
1145 "unsigned long"=>"ul",
1146 "long long"=>"ll",
1147 "unsigned long long"=>"ull"
1148);
1149
1150my %ConstantSuffixR =
1151reverse(%ConstantSuffix);
1152
1153my %OperatorMangling = (
1154 "~" => "co",
1155 "=" => "aS",
1156 "|" => "or",
1157 "^" => "eo",
1158 "&" => "an",#ad (addr)
1159 "==" => "eq",
1160 "!" => "nt",
1161 "!=" => "ne",
1162 "<" => "lt",
1163 "<=" => "le",
1164 "<<" => "ls",
1165 "<<=" => "lS",
1166 ">" => "gt",
1167 ">=" => "ge",
1168 ">>" => "rs",
1169 ">>=" => "rS",
1170 "()" => "cl",
1171 "%" => "rm",
1172 "[]" => "ix",
1173 "&&" => "aa",
1174 "||" => "oo",
1175 "*" => "ml",#de (deref)
1176 "++" => "pp",#
1177 "--" => "mm",#
1178 "new" => "nw",
1179 "delete" => "dl",
1180 "new[]" => "na",
1181 "delete[]" => "da",
1182 "+=" => "pL",
1183 "+" => "pl",#ps (pos)
1184 "-" => "mi",#ng (neg)
1185 "-=" => "mI",
1186 "*=" => "mL",
1187 "/=" => "dV",
1188 "&=" => "aN",
1189 "|=" => "oR",
1190 "%=" => "rM",
1191 "^=" => "eO",
1192 "/" => "dv",
1193 "->*" => "pm",
1194 "->" => "pt",#rf (ref)
1195 "," => "cm",
1196 "?" => "qu",
1197 "." => "dt",
1198 "sizeof"=> "sz"#st
1199);
1200
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001201my %Intrinsic_Keywords = map {$_=>1} (
1202 "true",
1203 "false",
1204 "_Bool",
1205 "_Complex",
1206 "const",
1207 "int",
1208 "long",
1209 "void",
1210 "short",
1211 "float",
1212 "volatile",
1213 "restrict",
1214 "unsigned",
1215 "signed",
1216 "char",
1217 "double",
1218 "class",
1219 "struct",
1220 "union",
1221 "enum"
1222);
1223
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001224my %GlibcHeader = map {$_=>1} (
1225 "aliases.h",
1226 "argp.h",
1227 "argz.h",
1228 "assert.h",
1229 "cpio.h",
1230 "ctype.h",
1231 "dirent.h",
1232 "envz.h",
1233 "errno.h",
1234 "error.h",
1235 "execinfo.h",
1236 "fcntl.h",
1237 "fstab.h",
1238 "ftw.h",
1239 "glob.h",
1240 "grp.h",
1241 "iconv.h",
1242 "ifaddrs.h",
1243 "inttypes.h",
1244 "langinfo.h",
1245 "limits.h",
1246 "link.h",
1247 "locale.h",
1248 "malloc.h",
1249 "math.h",
1250 "mntent.h",
1251 "monetary.h",
1252 "nl_types.h",
1253 "obstack.h",
1254 "printf.h",
1255 "pwd.h",
1256 "regex.h",
1257 "sched.h",
1258 "search.h",
1259 "setjmp.h",
1260 "shadow.h",
1261 "signal.h",
1262 "spawn.h",
1263 "stdarg.h",
1264 "stdint.h",
1265 "stdio.h",
1266 "stdlib.h",
1267 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001268 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001269 "tar.h",
1270 "termios.h",
1271 "time.h",
1272 "ulimit.h",
1273 "unistd.h",
1274 "utime.h",
1275 "wchar.h",
1276 "wctype.h",
1277 "wordexp.h" );
1278
1279my %GlibcDir = map {$_=>1} (
1280 "arpa",
1281 "bits",
1282 "gnu",
1283 "netinet",
1284 "net",
1285 "nfs",
1286 "rpc",
1287 "sys",
1288 "linux" );
1289
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001290my %WinHeaders = map {$_=>1} (
1291 "dos.h",
1292 "process.h",
1293 "winsock.h",
1294 "config-win.h",
1295 "mem.h",
1296 "windows.h",
1297 "winsock2.h",
1298 "crtdbg.h",
1299 "ws2tcpip.h"
1300);
1301
1302my %ObsoleteHeaders = map {$_=>1} (
1303 "iostream.h",
1304 "fstream.h"
1305);
1306
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001307my %AlienHeaders = map {$_=>1} (
1308 # Solaris
1309 "thread.h",
1310 "sys/atomic.h",
1311 # HPUX
1312 "sys/stream.h",
1313 # Symbian
1314 "AknDoc.h",
1315 # Atari ST
1316 "ext.h",
1317 "tos.h",
1318 # MS-DOS
1319 "alloc.h",
1320 # Sparc
1321 "sys/atomic.h"
1322);
1323
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001324my %ConfHeaders = map {$_=>1} (
1325 "atomic",
1326 "conf.h",
1327 "config.h",
1328 "configure.h",
1329 "build.h",
1330 "setup.h"
1331);
1332
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001333my %LocalIncludes = map {$_=>1} (
1334 "/usr/local/include",
1335 "/usr/local" );
1336
1337my %OS_AddPath=(
1338# These paths are needed if the tool cannot detect them automatically
1339 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001340 "include"=>[
1341 "/Library",
1342 "/Developer/usr/include"
1343 ],
1344 "lib"=>[
1345 "/Library",
1346 "/Developer/usr/lib"
1347 ],
1348 "bin"=>[
1349 "/Developer/usr/bin"
1350 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001351 },
1352 "beos"=>{
1353 # Haiku has GCC 2.95.3 by default
1354 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001355 "include"=>[
1356 "/boot/common",
1357 "/boot/develop"
1358 ],
1359 "lib"=>[
1360 "/boot/common/lib",
1361 "/boot/system/lib",
1362 "/boot/apps"
1363 ],
1364 "bin"=>[
1365 "/boot/common/bin",
1366 "/boot/system/bin",
1367 "/boot/develop/abi"
1368 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001369 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001370);
1371
1372my %Slash_Type=(
1373 "default"=>"/",
1374 "windows"=>"\\"
1375);
1376
1377my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1378
1379# Global Variables
1380my %COMMON_LANGUAGE=(
1381 1 => "C",
1382 2 => "C" );
1383
1384my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001385my $MAX_CPPFILT_FILE_SIZE = 50000;
1386my $CPPFILT_SUPPORT_FILE;
1387
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001388my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1389
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001390my $STDCXX_TESTING = 0;
1391my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001392my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001393
1394my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
1395my $CheckObjectsOnly = $CheckObjectsOnly_Opt;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001396
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001397my $TargetComponent;
1398
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001399my $CheckUndefined = 0;
1400
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001401# Set Target Component Name
1402if($TargetComponent_Opt) {
1403 $TargetComponent = lc($TargetComponent_Opt);
1404}
1405else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001406{ # default: library
1407 # other components: header, system, ...
1408 $TargetComponent = "library";
1409}
1410
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001411my $TOP_REF = "<a style='font-size:11px;' href='#Top'>to the top</a>";
1412
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001413my $SystemRoot;
1414
1415my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001416my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001417my %LOG_PATH;
1418my %DEBUG_PATH;
1419my %Cache;
1420my %LibInfo;
1421my $COMPILE_ERRORS = 0;
1422my %CompilerOptions;
1423my %CheckedDyLib;
1424my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1425
1426# Constants (#defines)
1427my %Constants;
1428my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001429my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001430
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001431# Extra Info
1432my %SymbolHeader;
1433my %KnownLibs;
1434
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001435# Templates
1436my %TemplateInstance;
1437my %BasicTemplate;
1438my %TemplateArg;
1439my %TemplateDecl;
1440my %TemplateMap;
1441
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001442# Types
1443my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001444my %SkipTypes = (
1445 "1"=>{},
1446 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001447my %CheckedTypes;
1448my %TName_Tid;
1449my %EnumMembName_Id;
1450my %NestedNameSpaces = (
1451 "1"=>{},
1452 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001453my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001454my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001455my %ClassVTable;
1456my %ClassVTable_Content;
1457my %VTableClass;
1458my %AllocableClass;
1459my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001460my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001461my %Class_SubClasses;
1462my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001463my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001464my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001465
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001466my %CheckedTypeInfo;
1467
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001468# Typedefs
1469my %Typedef_BaseName;
1470my %Typedef_Tr;
1471my %Typedef_Eq;
1472my %StdCxxTypedef;
1473my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001474my %MissedBase;
1475my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001476my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001477
1478# Symbols
1479my %SymbolInfo;
1480my %tr_name;
1481my %mangled_name_gcc;
1482my %mangled_name;
1483my %SkipSymbols = (
1484 "1"=>{},
1485 "2"=>{} );
1486my %SkipNameSpaces = (
1487 "1"=>{},
1488 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001489my %AddNameSpaces = (
1490 "1"=>{},
1491 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001492my %SymbolsList;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001493my %SkipSymbolsList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001494my %SymbolsList_App;
1495my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001496my %Symbol_Library = (
1497 "1"=>{},
1498 "2"=>{} );
1499my %Library_Symbol = (
1500 "1"=>{},
1501 "2"=>{} );
1502my %DepSymbol_Library = (
1503 "1"=>{},
1504 "2"=>{} );
1505my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001506 "1"=>{},
1507 "2"=>{} );
1508my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001509my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001510my %AddIntParams;
1511my %Interface_Impl;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001512my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001513my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001514my %Library_Needed= (
1515 "1"=>{},
1516 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001517
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001518# Extra Info
1519my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001520my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001521
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001522# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001523my %Include_Preamble = (
1524 "1"=>[],
1525 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001526my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001527my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001528my %HeaderName_Paths;
1529my %Header_Dependency;
1530my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001531my %Include_Paths = (
1532 "1"=>[],
1533 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001534my %INC_PATH_AUTODETECT = (
1535 "1"=>1,
1536 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001537my %Add_Include_Paths = (
1538 "1"=>[],
1539 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001540my %Skip_Include_Paths;
1541my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001542my %Header_ErrorRedirect;
1543my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001544my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001545my %Header_ShouldNotBeUsed;
1546my %RecursiveIncludes;
1547my %Header_Include_Prefix;
1548my %SkipHeaders;
1549my %SkipHeadersList=(
1550 "1"=>{},
1551 "2"=>{} );
1552my %SkipLibs;
1553my %Include_Order;
1554my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001555my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001556my %TUnit_Funcs;
1557my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001558
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001559my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001560 "1"=>0,
1561 "2"=>0 );
1562my %AutoPreambleMode = (
1563 "1"=>0,
1564 "2"=>0 );
1565my %MinGWMode = (
1566 "1"=>0,
1567 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001568my %Cpp0xMode = (
1569 "1"=>0,
1570 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001571
1572# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001573my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001574my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001575my %RegisteredSONAMEs;
1576my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001577
1578# System Objects
1579my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001580my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001581my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001582
1583# System Headers
1584my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001585my @DefaultCppPaths;
1586my @DefaultGccPaths;
1587my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001588my %DefaultCppHeader;
1589my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001590my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001591
1592# Merging
1593my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001594my $Version;
1595my %AddedInt;
1596my %RemovedInt;
1597my %AddedInt_Virt;
1598my %RemovedInt_Virt;
1599my %VirtualReplacement;
1600my %ChangedTypedef;
1601my %CompatRules;
1602my %IncompleteRules;
1603my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001604my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001605my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001606my %ReturnedClass;
1607my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001608my %SourceAlternative;
1609my %SourceAlternative_B;
1610my %SourceReplacement;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04001611my $CurrentSymbol; # for debugging
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001612
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001613# Calling Conventions
1614my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001615 1=>{ "R"=>0, "P"=>0 },
1616 2=>{ "R"=>0, "P"=>0 }
1617);
1618
1619# ABI Dump
1620my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001621
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001622# OS Compliance
1623my %TargetLibs;
1624my %TargetHeaders;
1625
1626# OS Specifics
1627my $OStarget = $OSgroup;
1628my %TargetTools;
1629
1630# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001631my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001632
1633# Recursion locks
1634my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001635my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001636my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001637my @RecurInclude;
1638my @RecurConstant;
1639
1640# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001641my %SystemPaths = (
1642 "include"=>[],
1643 "lib"=>[],
1644 "bin"=>[]
1645);
1646my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001647my $GCC_PATH;
1648
1649# Symbols versioning
1650my %SymVer = (
1651 "1"=>{},
1652 "2"=>{} );
1653
1654# Problem descriptions
1655my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001656my %CompatProblems_Constants;
1657my %CompatProblems_Impl;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001658my %TotalAffected;
1659
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001660# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001661my $ContentID = 1;
1662my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1663my $ContentSpanStart_Affected = "<span class=\"section_affected\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1664my $ContentSpanStart_Info = "<span class=\"section_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1665my $ContentSpanEnd = "</span>\n";
1666my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1667my $ContentDivEnd = "</div>\n";
1668my $Content_Counter = 0;
1669
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001670# Modes
1671my $JoinReport = 1;
1672my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001673
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04001674my %Severity_Val=(
1675 "High"=>3,
1676 "Medium"=>2,
1677 "Low"=>1,
1678 "Safe"=>-1
1679);
1680
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001681sub get_Modules()
1682{
1683 my $TOOL_DIR = get_dirname($0);
1684 if(not $TOOL_DIR)
1685 { # patch for MS Windows
1686 $TOOL_DIR = ".";
1687 }
1688 my @SEARCH_DIRS = (
1689 # tool's directory
1690 abs_path($TOOL_DIR),
1691 # relative path to modules
1692 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001693 # install path
1694 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001695 );
1696 foreach my $DIR (@SEARCH_DIRS)
1697 {
1698 if(not is_abs($DIR))
1699 { # relative path
1700 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1701 }
1702 if(-d $DIR."/modules") {
1703 return $DIR."/modules";
1704 }
1705 }
1706 exitStatus("Module_Error", "can't find modules");
1707}
1708
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001709my %LoadedModules = ();
1710
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001711sub loadModule($)
1712{
1713 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001714 if(defined $LoadedModules{$Name}) {
1715 return;
1716 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001717 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1718 if(not -f $Path) {
1719 exitStatus("Module_Error", "can't access \'$Path\'");
1720 }
1721 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001722 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001723}
1724
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001725sub readModule($$)
1726{
1727 my ($Module, $Name) = @_;
1728 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1729 if(not -f $Path) {
1730 exitStatus("Module_Error", "can't access \'$Path\'");
1731 }
1732 return readFile($Path);
1733}
1734
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001735sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001736{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001737 my $Number = $_[0];
1738 if(not $Number) {
1739 $Number = 1;
1740 }
1741 else {
1742 $Number = int($Number)+1;
1743 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001744 if($Number>3) {
1745 return $Number."th";
1746 }
1747 elsif($Number==1) {
1748 return "1st";
1749 }
1750 elsif($Number==2) {
1751 return "2nd";
1752 }
1753 elsif($Number==3) {
1754 return "3rd";
1755 }
1756 else {
1757 return $Number;
1758 }
1759}
1760
1761sub search_Tools($)
1762{
1763 my $Name = $_[0];
1764 return "" if(not $Name);
1765 if(my @Paths = keys(%TargetTools))
1766 {
1767 foreach my $Path (@Paths)
1768 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001769 if(-f join_P($Path, $Name)) {
1770 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001771 }
1772 if($CrossPrefix)
1773 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001774 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001775 if(-f $Candidate) {
1776 return $Candidate;
1777 }
1778 }
1779 }
1780 }
1781 else {
1782 return "";
1783 }
1784}
1785
1786sub synch_Cmd($)
1787{
1788 my $Name = $_[0];
1789 if(not $GCC_PATH)
1790 { # GCC was not found yet
1791 return "";
1792 }
1793 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001794 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001795 return $Candidate;
1796 }
1797 return "";
1798}
1799
1800sub get_CmdPath($)
1801{
1802 my $Name = $_[0];
1803 return "" if(not $Name);
1804 if(defined $Cache{"get_CmdPath"}{$Name}) {
1805 return $Cache{"get_CmdPath"}{$Name};
1806 }
1807 my %BinUtils = map {$_=>1} (
1808 "c++filt",
1809 "objdump",
1810 "readelf"
1811 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001812 if($BinUtils{$Name} and $GCC_PATH)
1813 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001814 if(my $Dir = get_dirname($GCC_PATH)) {
1815 $TargetTools{$Dir}=1;
1816 }
1817 }
1818 my $Path = search_Tools($Name);
1819 if(not $Path and $OSgroup eq "windows") {
1820 $Path = search_Tools($Name.".exe");
1821 }
1822 if(not $Path and $BinUtils{$Name})
1823 {
1824 if($CrossPrefix)
1825 { # user-defined prefix
1826 $Path = search_Cmd($CrossPrefix."-".$Name);
1827 }
1828 }
1829 if(not $Path and $BinUtils{$Name})
1830 {
1831 if(my $Candidate = synch_Cmd($Name))
1832 { # synch with GCC
1833 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001834 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001835 if(-f $Candidate) {
1836 $Path = $Candidate;
1837 }
1838 }
1839 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001840 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001841 $Path = $Candidate;
1842 }
1843 }
1844 }
1845 if(not $Path) {
1846 $Path = search_Cmd($Name);
1847 }
1848 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001849 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001850 $Path=search_Cmd($Name.".exe");
1851 }
1852 if($Path=~/\s/) {
1853 $Path = "\"".$Path."\"";
1854 }
1855 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1856}
1857
1858sub search_Cmd($)
1859{
1860 my $Name = $_[0];
1861 return "" if(not $Name);
1862 if(defined $Cache{"search_Cmd"}{$Name}) {
1863 return $Cache{"search_Cmd"}{$Name};
1864 }
1865 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1866 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1867 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001868 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001869 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001870 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001871 if(-f $CmdPath)
1872 {
1873 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001874 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001875 }
1876 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1877 }
1878 }
1879 return ($Cache{"search_Cmd"}{$Name} = "");
1880}
1881
1882sub get_CmdPath_Default($)
1883{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001884 return "" if(not $_[0]);
1885 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1886 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001887 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001888 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1889}
1890
1891sub get_CmdPath_Default_I($)
1892{ # search in PATH
1893 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001894 if($Name=~/find/)
1895 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001896 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001897 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001898 }
1899 }
1900 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001901 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001902 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001903 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001904 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001905 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001906 if($OSgroup eq "windows")
1907 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001908 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001909 return $Name;
1910 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001911 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001912 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001913 {
1914 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001915 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001916 }
1917 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001918 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001919}
1920
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001921sub classifyPath($)
1922{
1923 my $Path = $_[0];
1924 if($Path=~/[\*\[]/)
1925 { # wildcard
1926 $Path=~s/\*/.*/g;
1927 $Path=~s/\\/\\\\/g;
1928 return ($Path, "Pattern");
1929 }
1930 elsif($Path=~/[\/\\]/)
1931 { # directory or relative path
1932 return (path_format($Path, $OSgroup), "Path");
1933 }
1934 else {
1935 return ($Path, "Name");
1936 }
1937}
1938
1939sub readDescriptor($$)
1940{
1941 my ($LibVersion, $Content) = @_;
1942 return if(not $LibVersion);
1943 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1944 if(not $Content) {
1945 exitStatus("Error", "$DName is empty");
1946 }
1947 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001948 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001949 }
1950 $Content=~s/\/\*(.|\n)+?\*\///g;
1951 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001952
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001953 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1954 if($TargetVersion{$LibVersion}) {
1955 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1956 }
1957 if(not $Descriptor{$LibVersion}{"Version"}) {
1958 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1959 }
1960 if($Content=~/{RELPATH}/)
1961 {
1962 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1963 $Content =~ s/{RELPATH}/$RelDir/g;
1964 }
1965 else
1966 {
1967 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1968 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1969 }
1970 }
1971
1972 if(not $CheckObjectsOnly_Opt)
1973 {
1974 my $DHeaders = parseTag(\$Content, "headers");
1975 if(not $DHeaders) {
1976 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1977 }
1978 elsif(lc($DHeaders) ne "none")
1979 { # append the descriptor headers list
1980 if($Descriptor{$LibVersion}{"Headers"})
1981 { # multiple descriptors
1982 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
1983 }
1984 else {
1985 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1986 }
1987 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1988 {
1989 if(not -e $Path) {
1990 exitStatus("Access_Error", "can't access \'$Path\'");
1991 }
1992 }
1993 }
1994 }
1995 if(not $CheckHeadersOnly_Opt)
1996 {
1997 my $DObjects = parseTag(\$Content, "libs");
1998 if(not $DObjects) {
1999 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
2000 }
2001 elsif(lc($DObjects) ne "none")
2002 { # append the descriptor libraries list
2003 if($Descriptor{$LibVersion}{"Libs"})
2004 { # multiple descriptors
2005 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
2006 }
2007 else {
2008 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
2009 }
2010 foreach my $Path (split(/\s*\n\s*/, $DObjects))
2011 {
2012 if(not -e $Path) {
2013 exitStatus("Access_Error", "can't access \'$Path\'");
2014 }
2015 }
2016 }
2017 }
2018 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
2019 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002020 if(not -d $Path) {
2021 exitStatus("Access_Error", "can't access directory \'$Path\'");
2022 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002023 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002024 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002025 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002026 }
2027 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
2028 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002029 if(not -d $Path) {
2030 exitStatus("Access_Error", "can't access directory \'$Path\'");
2031 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002032 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002033 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002034 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002035 }
2036 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
2037 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002038 if(not -d $Path) {
2039 exitStatus("Access_Error", "can't access directory \'$Path\'");
2040 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002041 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002042 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002043 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002044 $TargetTools{$Path}=1;
2045 }
2046 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
2047 $CrossPrefix = $Prefix;
2048 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002049 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002050 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
2051 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002052 if(not -d $Path) {
2053 exitStatus("Access_Error", "can't access directory \'$Path\'");
2054 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002055 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002056 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002057 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002058 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002059 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002060 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
2061 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002062 if(not -d $Path) {
2063 exitStatus("Access_Error", "can't access directory \'$Path\'");
2064 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002065 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002066 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002067 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002068 }
2069 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002070 { # skip some auto-generated include paths
2071 if(not is_abs($Path))
2072 {
2073 if(my $P = abs_path($Path)) {
2074 $Path = $P;
2075 }
2076 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002077 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002078 }
2079 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002080 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002081 my ($CPath, $Type) = classifyPath($Path);
2082 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002083 }
2084 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002085 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
2086 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002087 if($Option!~/\A\-(Wl|l|L)/)
2088 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002089 $CompilerOptions{$LibVersion} .= " ".$Option;
2090 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002091 }
2092 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
2093 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
2094 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002095 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002096 my ($CPath, $Type) = classifyPath($Path);
2097 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002098 }
2099 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
2100 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
2101 {
2102 my ($CPath, $Type) = classifyPath($Path);
2103 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
2104 }
2105 if(my $DDefines = parseTag(\$Content, "defines"))
2106 {
2107 if($Descriptor{$LibVersion}{"Defines"})
2108 { # multiple descriptors
2109 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
2110 }
2111 else {
2112 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
2113 }
2114 }
2115 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
2116 {
2117 if($Order=~/\A(.+):(.+)\Z/) {
2118 $Include_Order{$LibVersion}{$1} = $2;
2119 }
2120 }
2121 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
2122 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002123 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002124 $SkipTypes{$LibVersion}{$Type_Name} = 1;
2125 }
2126 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
2127 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002128 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002129 $SkipSymbols{$LibVersion}{$Symbol} = 1;
2130 }
2131 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
2132 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
2133 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04002134 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
2135 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
2136 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002137 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
2138 $SkipConstants{$LibVersion}{$Constant} = 1;
2139 }
2140 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
2141 {
2142 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002143 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002144 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
2145 }
2146 else {
2147 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2148 }
2149 }
2150}
2151
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002152sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002153{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002154 my $CodeRef = shift(@_);
2155 my $Tag = shift(@_);
2156 if(not $Tag or not $CodeRef) {
2157 return undef;
2158 }
2159 my $Sp = 0;
2160 if(@_) {
2161 $Sp = shift(@_);
2162 }
2163 my $Start = index(${$CodeRef}, "<$Tag>");
2164 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002165 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002166 my $End = index(${$CodeRef}, "</$Tag>");
2167 if($End!=-1)
2168 {
2169 my $TS = length($Tag)+3;
2170 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2171 substr($Content, 0, $TS-1, ""); # cut start tag
2172 substr($Content, -$TS, $TS, ""); # cut end tag
2173 if(not $Sp)
2174 {
2175 $Content=~s/\A\s+//g;
2176 $Content=~s/\s+\Z//g;
2177 }
2178 if(substr($Content, 0, 1) ne "<") {
2179 $Content = xmlSpecChars_R($Content);
2180 }
2181 return $Content;
2182 }
2183 }
2184 return undef;
2185}
2186
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002187sub getInfo($)
2188{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002189 my $DumpPath = $_[0];
2190 return if(not $DumpPath or not -f $DumpPath);
2191
2192 readTUDump($DumpPath);
2193
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002194 # processing info
2195 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002196
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002197 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002198 setAnonTypedef_All();
2199 }
2200
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002201 getTypeInfo_All();
2202 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002203 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002204 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002205 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002206
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002207 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002208 %LibInfo = ();
2209 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002210 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002211 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002212 %TemplateDecl = ();
2213 %StdCxxTypedef = ();
2214 %MissedTypedef = ();
2215 %Typedef_Tr = ();
2216 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002217 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002218
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002219 # clean cache
2220 delete($Cache{"getTypeAttr"});
2221 delete($Cache{"getTypeDeclId"});
2222
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002223 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002224 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002225 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002226 }
2227 else
2228 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002229 if($BinaryOnly and not $ExtendedCheck)
2230 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002231 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002232 }
2233 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002234 remove_Unused($Version, "Extended");
2235 }
2236 }
2237
2238 if($CheckInfo)
2239 {
2240 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2241 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2242 }
2243
2244 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2245 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002246 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002247 }
2248
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002249 if($Debug) {
2250 # debugMangling($Version);
2251 }
2252}
2253
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002254sub readTUDump($)
2255{
2256 my $DumpPath = $_[0];
2257
2258 open(TU_DUMP, $DumpPath);
2259 local $/ = undef;
2260 my $Content = <TU_DUMP>;
2261 close(TU_DUMP);
2262
2263 unlink($DumpPath);
2264
2265 $Content=~s/\n[ ]+/ /g;
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04002266 my @Lines = split(/\n/, $Content);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002267
2268 # clean memory
2269 undef $Content;
2270
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002271 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002272
2273 foreach (0 .. $#Lines)
2274 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002275 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002276 { # get a number and attributes of a node
2277 next if(not $NodeType{$2});
2278 $LibInfo{$Version}{"info_type"}{$1}=$2;
2279 $LibInfo{$Version}{"info"}{$1}=$3;
2280 }
2281
2282 # clean memory
2283 delete($Lines[$_]);
2284 }
2285
2286 # clean memory
2287 undef @Lines;
2288}
2289
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002290sub simplifyConstants()
2291{
2292 foreach my $Constant (keys(%{$Constants{$Version}}))
2293 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002294 if(defined $Constants{$Version}{$Constant}{"Header"})
2295 {
2296 my $Value = $Constants{$Version}{$Constant}{"Value"};
2297 if(defined $EnumConstants{$Version}{$Value}) {
2298 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2299 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002300 }
2301 }
2302}
2303
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002304sub simplifyNames()
2305{
2306 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2307 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002308 if($Typedef_Eq{$Version}{$Base}) {
2309 next;
2310 }
2311 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2312 if($#Translations==0)
2313 {
2314 if(length($Translations[0])<=length($Base)) {
2315 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2316 }
2317 }
2318 else
2319 { # select most appropriate
2320 foreach my $Tr (@Translations)
2321 {
2322 if($Base=~/\A\Q$Tr\E/)
2323 {
2324 $Typedef_Eq{$Version}{$Base} = $Tr;
2325 last;
2326 }
2327 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002328 }
2329 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002330 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002331 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002332 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002333 if(not $TypeName) {
2334 next;
2335 }
2336 next if(index($TypeName,"<")==-1);# template instances only
2337 if($TypeName=~/>(::\w+)+\Z/)
2338 { # skip unused types
2339 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002340 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002341 foreach my $Base (sort {length($b)<=>length($a)}
2342 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002343 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002344 next if(not $Base);
2345 next if(index($TypeName,$Base)==-1);
2346 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002347 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002348 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002349 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2350 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2351 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002352 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002353 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2354 {
2355 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2356 {
2357 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2358 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002359 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002360 }
2361 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002362 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002363 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002364 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002365 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002366 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2367 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002368 }
2369}
2370
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002371sub setAnonTypedef_All()
2372{
2373 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2374 {
2375 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2376 {
2377 if(isAnon(getNameByInfo($InfoId))) {
2378 $TypedefToAnon{getTypeId($InfoId)} = 1;
2379 }
2380 }
2381 }
2382}
2383
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002384sub setTemplateParams_All()
2385{
2386 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2387 {
2388 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2389 setTemplateParams($_);
2390 }
2391 }
2392}
2393
2394sub setTemplateParams($)
2395{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002396 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002397 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002398 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002399 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002400 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002401 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002402 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002403 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002404 setTemplateInstParams($_[0], $TmplInst_Id);
2405 }
2406 }
2407
2408 $BasicTemplate{$Version}{$Tid} = $_[0];
2409
2410 if(my $Prms = getTreeAttr_Prms($_[0]))
2411 {
2412 if(my $Valu = getTreeAttr_Valu($Prms))
2413 {
2414 my $Vector = getTreeVec($Valu);
2415 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2416 {
2417 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2418 {
2419 if(my $Name = getNameByInfo($Val))
2420 {
2421 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2422 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2423 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2424 }
2425 else {
2426 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2427 }
2428 }
2429 }
2430 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002431 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002432 }
2433 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002434 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002435 {
2436 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2437 {
2438 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002439 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002440 }
2441 }
2442 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002443}
2444
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002445sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002446{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002447 my ($Tmpl, $Inst) = @_;
2448
2449 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002450 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002451 my ($Params_InfoId, $ElemId) = ();
2452 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2453 $Params_InfoId = $1;
2454 }
2455 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2456 $ElemId = $1;
2457 }
2458 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002459 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002460 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2461 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2462 {
2463 my ($PPos, $PTypeId) = ($1, $2);
2464 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2465 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002466 if($PType eq "template_type_parm") {
2467 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002468 }
2469 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002470 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2471 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002472 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002473 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002474 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002475 else
2476 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002477 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002478 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002479 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002480 }
2481 }
2482 }
2483}
2484
2485sub getTypeDeclId($)
2486{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002487 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002488 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002489 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2490 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2491 }
2492 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2493 {
2494 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2495 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2496 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002497 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002498 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002499 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002500}
2501
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002502sub getTypeInfo_All()
2503{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002504 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002505 { # support for GCC < 4.5
2506 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2507 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2508 # FIXME: check GCC versions
2509 addMissedTypes_Pre();
2510 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002511
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002512 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002513 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002514 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2515 if($IType=~/_type\Z/ and $IType ne "function_type"
2516 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002517 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002518 }
2519 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002520
2521 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002522 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002523 "Name" => "...",
2524 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002525 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002526 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002527 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002528
2529 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002530 { # support for GCC < 4.5
2531 addMissedTypes_Post();
2532 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002533
2534 if($ADD_TMPL_INSTANCES)
2535 {
2536 # templates
2537 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2538 {
2539 if(defined $TemplateMap{$Version}{$Tid}
2540 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2541 {
2542 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2543 {
2544 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2545 {
2546 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2547 {
2548 if(my %MAttr = getTypeAttr($MembTypeId))
2549 {
2550 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2551 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2552 }
2553 }
2554 }
2555 }
2556 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2557 {
2558 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2559 {
2560 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2561
2562 if($NBid ne $Bid)
2563 {
2564 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2565 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2566 }
2567 }
2568 }
2569 }
2570 }
2571 }
2572}
2573
2574sub createType($$)
2575{
2576 my ($Attr, $LibVersion) = @_;
2577 my $NewId = ++$MAX_ID;
2578
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002579 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002580 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002581 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002582
2583 return "$NewId";
2584}
2585
2586sub instType($$$)
2587{ # create template instances
2588 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002589
2590 if(not $TypeInfo{$LibVersion}{$Tid}) {
2591 return undef;
2592 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002593 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2594
2595 foreach my $Key (sort keys(%{$Map}))
2596 {
2597 if(my $Val = $Map->{$Key})
2598 {
2599 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2600
2601 if(defined $Attr->{"NameSpace"}) {
2602 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2603 }
2604 foreach (keys(%{$Attr->{"TParam"}})) {
2605 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2606 }
2607 }
2608 else
2609 { # remove absent
2610 # _Traits, etc.
2611 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002612 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002613 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2614 }
2615 foreach (keys(%{$Attr->{"TParam"}}))
2616 {
2617 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2618 delete($Attr->{"TParam"}{$_});
2619 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002620 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002621 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2622 }
2623 }
2624 }
2625 }
2626
2627 my $Tmpl = 0;
2628
2629 if(defined $Attr->{"TParam"})
2630 {
2631 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2632 {
2633 my $PName = $Attr->{"TParam"}{$_}{"name"};
2634
2635 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2636 {
2637 my %Base = get_BaseType($PTid, $LibVersion);
2638
2639 if($Base{"Type"} eq "TemplateParam"
2640 or defined $Base{"Template"})
2641 {
2642 $Tmpl = 1;
2643 last
2644 }
2645 }
2646 }
2647 }
2648
2649 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2650 return "$Id";
2651 }
2652 else
2653 {
2654 if(not $Tmpl) {
2655 delete($Attr->{"Template"});
2656 }
2657
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002658 my $New = createType($Attr, $LibVersion);
2659
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002660 my %EMap = ();
2661 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2662 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2663 }
2664 foreach (keys(%{$Map})) {
2665 $EMap{$_} = $Map->{$_};
2666 }
2667
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002668 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2669 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002670 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002671 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002672 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002673 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002674 {
2675 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2676
2677 if($NBid ne $Bid)
2678 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002679 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2680 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002681 }
2682 }
2683 }
2684
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002685 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002686 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002687 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2688 {
2689 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2690 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2691 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002692 }
2693 }
2694
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002695 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002696 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002697 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2698 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002699 }
2700 }
2701
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002702 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2703 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002704 }
2705
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002706 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002707 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002708}
2709
2710sub addMissedTypes_Pre()
2711{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002712 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002713 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2714 { # detecting missed typedefs
2715 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2716 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002717 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002718 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002719 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002720 if($TypeType eq "Unknown")
2721 { # template_type_parm
2722 next;
2723 }
2724 my $TypeDeclId = getTypeDeclId($TypeId);
2725 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2726 my $TypedefName = getNameByInfo($MissedTDid);
2727 next if(not $TypedefName);
2728 next if($TypedefName eq "__float80");
2729 next if(isAnon($TypedefName));
2730 if(not $TypeDeclId
2731 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002732 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002733 }
2734 }
2735 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002736 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002737 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002738 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002739 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002740 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002741 next;
2742 }
2743 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002744 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002745 if(not $TypedefName) {
2746 next;
2747 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002748 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002749 my %MissedInfo = ( # typedef info
2750 "Name" => $TypedefName,
2751 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002752 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002753 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002754 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002755 my ($H, $L) = getLocation($MissedTDid);
2756 $MissedInfo{"Header"} = $H;
2757 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002758 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002759 { # other types
2760 next;
2761 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002762 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002763 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002764 next;
2765 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002766 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002767 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002768 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002769 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002770 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002771 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002772 next;
2773 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002774 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002775 next;
2776 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002777 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002778 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002779 next;
2780 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002781 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002782 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002783 next;
2784 }
2785 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002786
2787 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2788
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002789 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002790 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002791 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002792 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002793 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002794
2795 # add missed & remove other
2796 $TypeInfo{$Version} = \%AddTypes;
2797 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002798}
2799
2800sub addMissedTypes_Post()
2801{
2802 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2803 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002804 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2805 {
2806 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2807 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2808 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2809 }
2810 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002811 }
2812}
2813
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002814sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002815{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002816 my $TypeId = $_[0];
2817 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2818 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002819 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002820 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002821 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002822}
2823
2824sub getArraySize($$)
2825{
2826 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002827 if(my $Size = getSize($TypeId))
2828 {
2829 my $Elems = $Size/$BYTE_SIZE;
2830 while($BaseName=~s/\s*\[(\d+)\]//) {
2831 $Elems/=$1;
2832 }
2833 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2834 {
2835 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2836 $Elems/=$BasicSize;
2837 }
2838 }
2839 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002840 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002841 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002842}
2843
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002844sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002845{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002846 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002847 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002848 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2849 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002850 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002851 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2852 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2853 if(not $NodeType)
2854 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002855 return ();
2856 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002857 if($NodeType eq "tree_vec")
2858 {
2859 if($Pos!=$#Positions)
2860 { # select last vector of parameters ( ns<P1>::type<P2> )
2861 next;
2862 }
2863 }
2864 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2865 foreach my $P (@Params)
2866 {
2867 if($P eq "") {
2868 return ();
2869 }
2870 elsif($P ne "\@skip\@") {
2871 @TmplParams = (@TmplParams, $P);
2872 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002873 }
2874 }
2875 return @TmplParams;
2876}
2877
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002878sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002879{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002880 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002881 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002882 if(defined $TypeInfo{$Version}{$TypeId}
2883 and $TypeInfo{$Version}{$TypeId}{"Name"})
2884 { # already created
2885 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002886 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002887 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2888 { # incomplete type
2889 return ();
2890 }
2891 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2892
2893 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002894 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002895
2896 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2897 {
2898 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2899 {
2900 if($Info=~/qual[ ]*:/)
2901 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002902 my $NewId = ++$MAX_ID;
2903
2904 $MissedBase{$Version}{$TypeId} = "$NewId";
2905 $MissedBase_R{$Version}{$NewId} = $TypeId;
2906 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2907 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002908 }
2909 }
2910 $TypeAttr{"Type"} = "Typedef";
2911 }
2912 else {
2913 $TypeAttr{"Type"} = getTypeType($TypeId);
2914 }
2915
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002916 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2917 {
2918 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2919 { # local code
2920 return ();
2921 }
2922 }
2923
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002924 if($TypeAttr{"Type"} eq "Unknown") {
2925 return ();
2926 }
2927 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2928 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002929 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002930 if(my $TName = $TypeAttr{"Name"})
2931 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002932 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002933 $TName_Tid{$Version}{$TName} = $TypeId;
2934 return %TypeAttr;
2935 }
2936 else {
2937 return ();
2938 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002939 }
2940 elsif($TypeAttr{"Type"} eq "Array")
2941 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002942 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2943 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002944 return ();
2945 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002946 if(my $Algn = getAlgn($TypeId)) {
2947 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2948 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002949 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002950 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002951 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002952 if(not $BTAttr{"Name"}) {
2953 return ();
2954 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002955 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002956 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002957 if(my $Size = getSize($TypeId)) {
2958 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2959 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002960 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002961 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2962 }
2963 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002964 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002965 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002966 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002967 else
2968 {
2969 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002970 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002971 $TypeAttr{"Name"} = $1."[]".$2;
2972 }
2973 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002974 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002975 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002976 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002977 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002978 if($BTAttr{"Header"}) {
2979 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002980 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002981 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002982 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2983 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002984 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002985 return ();
2986 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002987 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002988 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002989 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002990 if($TypeAttr{"Name"})
2991 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002992 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002993
2994 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2995 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002996 { # NOTE: register only one int: with built-in decl
2997 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2998 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2999 }
3000 }
3001 return %TypeAttr;
3002 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003003 else {
3004 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003005 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003006 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003007 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
3008 {
3009 %TypeAttr = getTrivialTypeAttr($TypeId);
3010 if($TypeAttr{"Name"})
3011 {
3012 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
3013 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3014 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3015 }
3016 return %TypeAttr;
3017 }
3018 else {
3019 return ();
3020 }
3021 }
3022 elsif($TypeAttr{"Type"} eq "SizeOf")
3023 {
3024 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
3025 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
3026 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
3027 if($TypeAttr{"Name"})
3028 {
3029 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
3030 return %TypeAttr;
3031 }
3032 else {
3033 return ();
3034 }
3035 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003036 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003037 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003038 my ($BTid, $BTSpec) = selectBaseType($TypeId);
3039 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003040 return ();
3041 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003042 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003043 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003044 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003045 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003046 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003047 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003048 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003050 }
3051 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003052 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003053 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003054 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003055 return ();
3056 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003057 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003058 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003059 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003060 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003061 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003062 }
3063 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003064 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003065 {
3066 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003067 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003068 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003069 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003070 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
3071 }
3072 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003073 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003074 }
3075 }
3076 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003077 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003078 }
3079 if($TypeAttr{"Type"} eq "Typedef")
3080 {
3081 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003082
3083 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
3084 return ();
3085 }
3086
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003087 if(isAnon($TypeAttr{"Name"}))
3088 { # anon typedef to anon type: ._N
3089 return ();
3090 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003091
3092 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
3093 { # artificial typedef of "struct X" to "X"
3094 $TypeAttr{"Artificial"} = 1;
3095 }
3096
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003097 if(my $NS = getNameSpace($TypeDeclId))
3098 {
3099 my $TypeName = $TypeAttr{"Name"};
3100 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
3101 { # "some_type" is the typedef to "struct some_type" in C++
3102 if($3) {
3103 $TypeAttr{"Name"} = $3."::".$TypeName;
3104 }
3105 }
3106 else
3107 {
3108 $TypeAttr{"NameSpace"} = $NS;
3109 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003110
3111 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
3112 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
3113 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003114 if($BTAttr{"NameSpace"}
3115 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003116 { # types like "std::fpos<__mbstate_t>" are
3117 # not covered by typedefs in the TU dump
3118 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003119 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3120 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003121 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003122 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003123 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003124 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003125 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003126 }
3127 }
3128 }
3129 }
3130 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003131 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003132 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003133 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003134 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
3135 { # typedef int*const TYPEDEF; // first
3136 # int foo(TYPEDEF p); // const is optimized out
3137 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
3138 if($BTAttr{"Name"}=~/</)
3139 {
3140 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
3141 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3142 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003143 }
3144 }
3145 }
3146 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
3147 }
3148 if(not $TypeAttr{"Size"})
3149 {
3150 if($TypeAttr{"Type"} eq "Pointer") {
3151 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3152 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003153 elsif($BTAttr{"Size"}) {
3154 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003155 }
3156 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003157 if(my $Algn = getAlgn($TypeId)) {
3158 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3159 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003160 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003161 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3162 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003163 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003164 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003165 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003166 { # typedef to "class Class"
3167 # should not be registered in TName_Tid
3168 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3169 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3170 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003171 }
3172 return %TypeAttr;
3173 }
3174}
3175
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003176sub getTreeVec($)
3177{
3178 my %Vector = ();
3179 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3180 {
3181 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3182 { # string length is N-1 because of the null terminator
3183 $Vector{$1} = $2;
3184 }
3185 }
3186 return \%Vector;
3187}
3188
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003189sub get_TemplateParam($$)
3190{
3191 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003192 return () if(not $Type_Id);
3193 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3194 return () if(not $NodeType);
3195 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003196 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003197 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003198 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003199 my $Num = getNodeIntCst($Type_Id);
3200 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003201 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003202 }
3203 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003204 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003205 }
3206 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003207 elsif($NodeType eq "string_cst") {
3208 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003209 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003210 elsif($NodeType eq "tree_vec")
3211 {
3212 my $Vector = getTreeVec($Type_Id);
3213 my @Params = ();
3214 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3215 {
3216 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3217 push(@Params, $P2);
3218 }
3219 }
3220 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003221 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003222 elsif($NodeType eq "parm_decl")
3223 {
3224 (getNameByInfo($Type_Id));
3225 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003226 else
3227 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003228 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003229 my $PName = $ParamAttr{"Name"};
3230 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003231 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003232 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003233 if($PName=~/\>/)
3234 {
3235 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003236 $PName = $Cover;
3237 }
3238 }
3239 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003240 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003241 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3242 # template<typename _Key, typename _Compare = std::less<_Key>
3243 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3244 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3245 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3246 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003247 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003248 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003249 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003250 }
3251}
3252
3253sub cover_stdcxx_typedef($)
3254{
3255 my $TypeName = $_[0];
3256 if(my @Covers = sort {length($a)<=>length($b)}
3257 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3258 { # take the shortest typedef
3259 # FIXME: there may be more than
3260 # one typedefs to the same type
3261 return $Covers[0];
3262 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003263 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003264 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3265 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3266 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003267 if(my $Cover = $Covers[0])
3268 {
3269 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3270 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3271 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003272 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003273 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003274}
3275
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003276sub getNodeIntCst($)
3277{
3278 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003279 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003280 if($EnumMembName_Id{$Version}{$CstId}) {
3281 return $EnumMembName_Id{$Version}{$CstId};
3282 }
3283 elsif((my $Value = getTreeValue($CstId)) ne "")
3284 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003285 if($Value eq "0")
3286 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003287 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003288 return "false";
3289 }
3290 else {
3291 return "0";
3292 }
3293 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003294 elsif($Value eq "1")
3295 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003296 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003297 return "true";
3298 }
3299 else {
3300 return "1";
3301 }
3302 }
3303 else {
3304 return $Value;
3305 }
3306 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003307 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003308}
3309
3310sub getNodeStrCst($)
3311{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003312 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3313 {
3314 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003315 {
3316 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3317 { # string length is N-1 because of the null terminator
3318 return substr($1, 0, $2-1);
3319 }
3320 else
3321 { # identifier_node
3322 return substr($1, 0, $2);
3323 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003325 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003326 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003327}
3328
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003329sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003330{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003331 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003332 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3333 if($Type eq "FieldPtr") {
3334 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3335 }
3336 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3337 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003338 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003339 if($Type eq "MethodPtr")
3340 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003341 if(my $Size = getSize($TypeId))
3342 {
3343 $Size/=$BYTE_SIZE;
3344 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003345 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003346 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003347 if(my $Algn = getAlgn($TypeId)) {
3348 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3349 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003350 # Return
3351 if($Type eq "FieldPtr")
3352 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003353 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003354 if($ReturnAttr{"Name"}) {
3355 $MemPtrName .= $ReturnAttr{"Name"};
3356 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003357 $TypeAttr{"Return"} = $PtrId;
3358 }
3359 else
3360 {
3361 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3362 {
3363 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003364 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3365 if(not $ReturnAttr{"Name"})
3366 { # templates
3367 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003368 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003369 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003370 $TypeAttr{"Return"} = $ReturnTypeId;
3371 }
3372 }
3373 # Class
3374 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3375 {
3376 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003377 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003378 if($Class{"Name"}) {
3379 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3380 }
3381 else {
3382 $MemPtrName .= " (*)";
3383 }
3384 }
3385 else {
3386 $MemPtrName .= " (*)";
3387 }
3388 # Parameters
3389 if($Type eq "FuncPtr"
3390 or $Type eq "MethodPtr")
3391 {
3392 my @ParamTypeName = ();
3393 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3394 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003395 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003396 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003397 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003398 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003399 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3400 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003401 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003402 my $PTypeId = $1;
3403 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003404 if(not $ParamAttr{"Name"})
3405 { # templates (template_type_parm), etc.
3406 return ();
3407 }
3408 if($ParamAttr{"Name"} eq "void") {
3409 last;
3410 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003411 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003412 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003413 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003414 push(@ParamTypeName, $ParamAttr{"Name"});
3415 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003416 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3417 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003418 }
3419 else {
3420 last;
3421 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003422 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003423 else {
3424 last;
3425 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003426 }
3427 }
3428 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3429 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003430 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003431 return %TypeAttr;
3432}
3433
3434sub getTreeTypeName($)
3435{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003436 my $TypeId = $_[0];
3437 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003438 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003439 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003440 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003441 if(my $Name = getNameByInfo($TypeId))
3442 { # bit_size_type
3443 return $Name;
3444 }
3445 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003446 return "unsigned int";
3447 }
3448 else {
3449 return "int";
3450 }
3451 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003452 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003453 return getNameByInfo($1);
3454 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003455 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003456 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003457}
3458
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003459sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003460{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003461 my $Ptd = pointTo($_[0]);
3462 return 0 if(not $Ptd);
3463 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003464 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003465 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3466 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003467 }
3468 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003469 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3470 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003471 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003472 if($InfoT1 eq "pointer_type"
3473 and $InfoT2 eq "function_type") {
3474 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003475 }
3476 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003477 return 0;
3478}
3479
3480sub isMethodPtr($)
3481{
3482 my $Ptd = pointTo($_[0]);
3483 return 0 if(not $Ptd);
3484 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3485 {
3486 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3487 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3488 and $Info=~/ ptrmem /) {
3489 return 1;
3490 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003491 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003492 return 0;
3493}
3494
3495sub isFieldPtr($)
3496{
3497 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3498 {
3499 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3500 and $Info=~/ ptrmem /) {
3501 return 1;
3502 }
3503 }
3504 return 0;
3505}
3506
3507sub pointTo($)
3508{
3509 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3510 {
3511 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3512 return $1;
3513 }
3514 }
3515 return "";
3516}
3517
3518sub getTypeTypeByTypeId($)
3519{
3520 my $TypeId = $_[0];
3521 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3522 {
3523 my $NType = $NodeType{$TType};
3524 if($NType eq "Intrinsic") {
3525 return $NType;
3526 }
3527 elsif(isFuncPtr($TypeId)) {
3528 return "FuncPtr";
3529 }
3530 elsif(isMethodPtr($TypeId)) {
3531 return "MethodPtr";
3532 }
3533 elsif(isFieldPtr($TypeId)) {
3534 return "FieldPtr";
3535 }
3536 elsif($NType ne "Other") {
3537 return $NType;
3538 }
3539 }
3540 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003541}
3542
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003543my %UnQual = (
3544 "r"=>"restrict",
3545 "v"=>"volatile",
3546 "c"=>"const",
3547 "cv"=>"const volatile"
3548);
3549
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003550sub getQual($)
3551{
3552 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003553 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3554 {
3555 my ($Qual, $To) = ();
3556 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3557 $Qual = $UnQual{$1};
3558 }
3559 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3560 $To = $1;
3561 }
3562 if($Qual and $To) {
3563 return ($Qual, $To);
3564 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003565 }
3566 return ();
3567}
3568
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003569sub getQualType($)
3570{
3571 if($_[0] eq "const volatile") {
3572 return "ConstVolatile";
3573 }
3574 return ucfirst($_[0]);
3575}
3576
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003577sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003578{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003579 my $TypeId = $_[0];
3580 my $TypeDeclId = getTypeDeclId($TypeId);
3581 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003582 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003583 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3584 return "Typedef";
3585 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003586 }
3587 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3588 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003589 if(($Qual or $To) and $TypeDeclId
3590 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003591 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003592 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003593 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003594 elsif(not $MissedBase_R{$Version}{$TypeId}
3595 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003596 return "Typedef";
3597 }
3598 elsif($Qual)
3599 { # qualified types
3600 return getQualType($Qual);
3601 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003602
3603 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3604 { # typedef struct { ... } name
3605 $TypeTypedef{$Version}{$TypeId} = $1;
3606 }
3607
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003608 my $TypeType = getTypeTypeByTypeId($TypeId);
3609 if($TypeType eq "Struct")
3610 {
3611 if($TypeDeclId
3612 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3613 return "Template";
3614 }
3615 }
3616 return $TypeType;
3617}
3618
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003619sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003620{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003621 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003622 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003623 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3624 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3625 return 0;
3626 }
3627 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3628 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003629 if(my $TDid = getTypeDeclId($_[0]))
3630 {
3631 if(getTypeId($TDid) eq $_[0]
3632 and getNameByInfo($TDid))
3633 {
3634 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3635 return $1;
3636 }
3637 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003638 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003639 }
3640 }
3641 return 0;
3642}
3643
3644sub selectBaseType($)
3645{
3646 my $TypeId = $_[0];
3647 if(defined $MissedTypedef{$Version}{$TypeId})
3648 { # add missed typedefs
3649 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3650 return ($TypeId, "");
3651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003652 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003653 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3654 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003655
3656 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3657 my $MB = $MissedBase{$Version}{$TypeId};
3658
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003659 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003660 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003661 and (getTypeId($1) ne $TypeId)
3662 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003663 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003664 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003665 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003666 elsif($MB)
3667 { # add base
3668 return ($MB, "");
3669 }
3670 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003671 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003672 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003673 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003674 elsif($Qual or $To)
3675 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003676 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003677 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003678 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003679 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003680 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003681 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003682 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003683 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003684 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003685 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003686 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003687 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003688 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003689 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003690 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003691 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003692 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003693 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003694 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003695 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003696
3697 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003698}
3699
3700sub getSymbolInfo_All()
3701{
3702 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3703 { # reverse order
3704 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003705 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003706 }
3707 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003708
3709 if($ADD_TMPL_INSTANCES)
3710 {
3711 # templates
3712 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3713 {
3714 my %Map = ();
3715
3716 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3717 {
3718 if(defined $TemplateMap{$Version}{$ClassId})
3719 {
3720 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3721 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3722 }
3723 }
3724 }
3725
3726 if(defined $TemplateMap{$Version}{$Sid})
3727 {
3728 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3729 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3730 }
3731 }
3732
3733 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3734 {
3735 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3736 {
3737 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3738 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3739 }
3740 }
3741 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3742 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3743 }
3744 }
3745 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003746}
3747
3748sub getVarInfo_All()
3749{
3750 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3751 { # reverse order
3752 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003753 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003754 }
3755 }
3756}
3757
3758sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003759 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003760}
3761
3762sub getVarInfo($)
3763{
3764 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003765 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003766 {
3767 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3768 if($NSInfoType and $NSInfoType eq "function_decl") {
3769 return;
3770 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003771 }
3772 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3773 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3774 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3775 delete($SymbolInfo{$Version}{$InfoId});
3776 return;
3777 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003778 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003779 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003780 delete($SymbolInfo{$Version}{$InfoId});
3781 return;
3782 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003783 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3784 delete($SymbolInfo{$Version}{$InfoId});
3785 return;
3786 }
3787 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003788 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3789 {
3790 if($OSgroup eq "windows")
3791 { # cut the offset
3792 $MnglName=~s/\@\d+\Z//g;
3793 }
3794 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3795 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003796 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003797 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003798 { # validate mangled name
3799 delete($SymbolInfo{$Version}{$InfoId});
3800 return;
3801 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003802 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003803 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003804 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003805 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003806 }
3807 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3808 { # non-public global data
3809 delete($SymbolInfo{$Version}{$InfoId});
3810 return;
3811 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003812 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003813 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003814 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003815 if(not defined $TypeInfo{$Version}{$Rid}
3816 or not $TypeInfo{$Version}{$Rid}{"Name"})
3817 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003818 delete($SymbolInfo{$Version}{$InfoId});
3819 return;
3820 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003821 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3822 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003823 if(defined $Val) {
3824 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3825 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003826 }
3827 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003828 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3829 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003830 if(not defined $TypeInfo{$Version}{$ClassId}
3831 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3832 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003833 delete($SymbolInfo{$Version}{$InfoId});
3834 return;
3835 }
3836 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003837 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3838 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003839 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003840 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003841 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003842 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003843 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003844 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003845 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003846 if(not $CheckHeadersOnly)
3847 {
3848 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3849 {
3850 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3851 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3852 {
3853 if(link_symbol($ShortName, $Version, "-Deps"))
3854 { # "const" global data is mangled as _ZL... in the TU dump
3855 # but not mangled when compiling a C shared library
3856 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3857 }
3858 }
3859 }
3860 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003861 if($COMMON_LANGUAGE{$Version} eq "C++")
3862 {
3863 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3864 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003865 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003866 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3867 }
3868 }
3869 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3870 { # try to mangle symbol (link with libraries)
3871 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3872 }
3873 if($OStarget eq "windows")
3874 {
3875 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3876 { # link MS C++ symbols from library with GCC symbols from headers
3877 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3878 }
3879 }
3880 }
3881 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3882 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3883 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003884 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3885 {
3886 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3887 { # non-target symbols
3888 delete($SymbolInfo{$Version}{$InfoId});
3889 return;
3890 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003891 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003892 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3893 {
3894 if(defined $MissedTypedef{$Version}{$Rid})
3895 {
3896 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3897 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3898 }
3899 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003900 }
3901 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003902 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003903 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3904 }
3905 if($ShortName=~/\A(_Z|\?)/) {
3906 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3907 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003908
3909 if($ExtraDump) {
3910 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3911 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003912}
3913
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003914sub isConstType($$)
3915{
3916 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003917 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003918 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003919 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003920 }
3921 return ($Base{"Type"} eq "Const");
3922}
3923
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003924sub getTrivialName($$)
3925{
3926 my ($TypeInfoId, $TypeId) = @_;
3927 my %TypeAttr = ();
3928 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3929 if(not $TypeAttr{"Name"}) {
3930 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3931 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003932 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003933 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003934 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003935 if(isAnon($TypeAttr{"Name"}))
3936 {
3937 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003938 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003939 { # searching for a first not anon scope
3940 if($NSId eq $NameSpaceId) {
3941 last;
3942 }
3943 else
3944 {
3945 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3946 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003947 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003948 last;
3949 }
3950 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003951 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003952 }
3953 }
3954 else
3955 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003956 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003957 {
3958 if($NameSpaceId ne $TypeId) {
3959 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3960 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003961 }
3962 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003963 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003964 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3965 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003966 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003967 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003968 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003969 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003970 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003971 if($TypeAttr{"NameSpace"}) {
3972 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3973 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003974 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003975 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3976 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003977 {
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04003978 if(my @TParams = getTParams($TypeId, "Type")) {
3979 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
3980 }
3981 else {
3982 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."<...>", "T");
3983 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003984 }
3985 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3986}
3987
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003988sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003989{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003990 my $TypeId = $_[0];
3991 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003992
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003993 my %TypeAttr = ();
3994
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003995 if($TemplateDecl{$Version}{$TypeId})
3996 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003997 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003998 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003999
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004000 setTypeAccess($TypeId, \%TypeAttr);
4001 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
4002 if(isBuiltIn($TypeAttr{"Header"}))
4003 {
4004 delete($TypeAttr{"Header"});
4005 delete($TypeAttr{"Line"});
4006 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04004007
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004008 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004009 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
4010 if(not $TypeAttr{"Name"}) {
4011 return ();
4012 }
4013 if(not $TypeAttr{"NameSpace"}) {
4014 delete($TypeAttr{"NameSpace"});
4015 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004016
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +04004017 if($TypeAttr{"Type"} eq "Intrinsic")
4018 {
4019 if(defined $TypeAttr{"Header"})
4020 {
4021 if($TypeAttr{"Header"}=~/\Adump[1-2]\.[ih]\Z/)
4022 { # support for SUSE 11.2
4023 # integer_type has srcp dump{1-2}.i
4024 delete($TypeAttr{"Header"});
4025 }
4026 }
4027 }
4028
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004029 my $Tmpl = undef;
4030
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004031 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004032 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004033 $Tmpl = $BasicTemplate{$Version}{$TypeId};
4034
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004035 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004036 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004037 foreach my $Pos (0 .. $#TParams)
4038 {
4039 my $Val = $TParams[$Pos];
4040 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
4041
4042 if(not defined $TypeAttr{"Template"})
4043 {
4044 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
4045
4046 if($Base{"Type"} eq "TemplateParam"
4047 or defined $Base{"Template"}) {
4048 $TypeAttr{"Template"} = 1;
4049 }
4050 }
4051
4052 if($Tmpl)
4053 {
4054 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
4055 {
4056 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
4057
4058 if($Val eq $Arg) {
4059 $TypeAttr{"Template"} = 1;
4060 }
4061 }
4062 }
4063 }
4064
4065 if($Tmpl)
4066 {
4067 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
4068 {
4069 if($Pos>$#TParams)
4070 {
4071 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
4072 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
4073 }
4074 }
4075 }
4076 }
4077
4078 if($ADD_TMPL_INSTANCES)
4079 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004080 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004081 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004082 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004083 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004084 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004085 {
4086 if(my $Flds = getTreeAttr_Flds($MainInst)) {
4087 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
4088 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004089 }
4090 if(not getTreeAttr_Binf($TypeId))
4091 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004092 if(my $Binf = getTreeAttr_Binf($MainInst)) {
4093 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
4094 }
4095 }
4096 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004097 }
4098 }
4099 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004100
4101 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
4102
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004103 if(my $Size = getSize($TypeId))
4104 {
4105 $Size = $Size/$BYTE_SIZE;
4106 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004107 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004108 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004109 {
4110 if($ExtraDump)
4111 {
4112 if(not defined $TypeAttr{"Memb"}
4113 and not $Tmpl)
4114 { # declaration only
4115 $TypeAttr{"Forward"} = 1;
4116 }
4117 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004118 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004119
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004120 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004121 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004122 {
4123 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004124 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004125 }
4126 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004127 or $TypeAttr{"Type"} eq "Class")
4128 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004129 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004130 if($Skip) {
4131 return ();
4132 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004133 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004134 if(my $Algn = getAlgn($TypeId)) {
4135 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
4136 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004137 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004138
4139 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
4140 {
4141 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004142 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004143 {
4144 if(not isAnon($TypeAttr{"Name"})) {
4145 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
4146 }
4147 }
4148 }
4149
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004150 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004151 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4152 {
4153 my @Entries = split(/\n/, $VTable);
4154 foreach (1 .. $#Entries)
4155 {
4156 my $Entry = $Entries[$_];
4157 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004158 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004159 }
4160 }
4161 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004162
4163 if($TypeAttr{"Type"} eq "Enum")
4164 {
4165 if(not $TypeAttr{"NameSpace"})
4166 {
4167 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4168 {
4169 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004170 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004171 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004172 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004173 "Header"=>$TypeAttr{"Header"}
4174 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004175 if(isAnon($TypeAttr{"Name"}))
4176 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004177 if($ExtraDump
4178 or is_target_header($TypeAttr{"Header"}, $Version))
4179 {
4180 %{$Constants{$Version}{$MName}} = (
4181 "Value" => $MVal,
4182 "Header" => $TypeAttr{"Header"}
4183 );
4184 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004185 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004186 }
4187 }
4188 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004189 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004190 {
4191 if(defined $TypedefToAnon{$TypeId}) {
4192 $TypeAttr{"AnonTypedef"} = 1;
4193 }
4194 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004195
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004196 return %TypeAttr;
4197}
4198
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004199sub simplifyVTable($)
4200{
4201 my $Content = $_[0];
4202 if($Content=~s/ \[with (.+)]//)
4203 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4204 if(my @Elems = separate_Params($1, 0, 0))
4205 {
4206 foreach my $Elem (@Elems)
4207 {
4208 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4209 {
4210 my ($Arg, $Val) = ($1, $2);
4211
4212 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4213 $Content=~s/,\s*$Arg\b//g;
4214 }
4215 else {
4216 $Content=~s/\b$Arg\b/$Val/g;
4217 }
4218 }
4219 }
4220 }
4221 }
4222
4223 return $Content;
4224}
4225
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004226sub detect_lang($)
4227{
4228 my $TypeId = $_[0];
4229 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004230 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004231 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004232 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4233 }
4234 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004235 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004236 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004237 while($Fncs)
4238 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004239 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004240 return 1;
4241 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004242 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004243 }
4244 }
4245 return 0;
4246}
4247
4248sub setSpec($$)
4249{
4250 my ($TypeId, $TypeAttr) = @_;
4251 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4252 if($Info=~/\s+spec\s+/) {
4253 $TypeAttr->{"Spec"} = 1;
4254 }
4255}
4256
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004257sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004258{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004259 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004260 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004261 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004262 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004263 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004264 my $Pos = 0;
4265 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4266 {
4267 my ($Access, $BInfoId) = ($1, $2);
4268 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04004269
4270 if($ClassId==$TypeId)
4271 { # class A<N>:public A<N-1>
4272 next;
4273 }
4274
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004275 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4276 if(not $CType or $CType eq "template_type_parm"
4277 or $CType eq "typename_type")
4278 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004279 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004280 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004281 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004282 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004283 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4284 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004285 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004286 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4287 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004288 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004289 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004290 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004291 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4292 }
4293 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004294 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004295 }
4296 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004297 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004298}
4299
4300sub getBinfClassId($)
4301{
4302 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
4303 $Info=~/type[ ]*:[ ]*@(\d+) /;
4304 return $1;
4305}
4306
4307sub unmangledFormat($$)
4308{
4309 my ($Name, $LibVersion) = @_;
4310 $Name = uncover_typedefs($Name, $LibVersion);
4311 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4312 $Name=~s/\(\w+\)(\d)/$1/;
4313 return $Name;
4314}
4315
4316sub modelUnmangled($$)
4317{
4318 my ($InfoId, $Compiler) = @_;
4319 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4320 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4321 }
4322 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4323 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4324 $PureSignature = "~".$PureSignature;
4325 }
4326 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4327 {
4328 my (@Params, @ParamTypes) = ();
4329 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4330 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4331 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4332 }
4333 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4334 { # checking parameters
4335 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004336 my $PName = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004337 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004338 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004339
4340 if($PName eq "this"
4341 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method")
4342 {
4343 next;
4344 }
4345
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004346 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004347 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004348 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004349 }
4350 @ParamTypes = (@ParamTypes, $PTName);
4351 }
4352 if(@ParamTypes) {
4353 $PureSignature .= "(".join(", ", @ParamTypes).")";
4354 }
4355 else
4356 {
4357 if($Compiler eq "MSVC")
4358 {
4359 $PureSignature .= "(void)";
4360 }
4361 else
4362 { # GCC
4363 $PureSignature .= "()";
4364 }
4365 }
4366 $PureSignature = delete_keywords($PureSignature);
4367 }
4368 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4369 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004370 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004371 $PureSignature = $ClassName."::".$PureSignature;
4372 }
4373 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4374 $PureSignature = $NS."::".$PureSignature;
4375 }
4376 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4377 $PureSignature .= " const";
4378 }
4379 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4380 $PureSignature .= " volatile";
4381 }
4382 my $ShowReturn = 0;
4383 if($Compiler eq "MSVC"
4384 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4385 {
4386 $ShowReturn=1;
4387 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004388 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4389 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004390 {
4391 $ShowReturn=1;
4392 }
4393 if($ShowReturn)
4394 { # mangled names for template function specializations include return value
4395 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4396 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004397 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004398 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4399 $PureSignature = $ReturnName." ".$PureSignature;
4400 }
4401 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004402 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004403}
4404
4405sub mangle_symbol($$$)
4406{ # mangling for simple methods
4407 # see gcc-4.6.0/gcc/cp/mangle.c
4408 my ($InfoId, $LibVersion, $Compiler) = @_;
4409 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4410 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4411 }
4412 my $Mangled = "";
4413 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004414 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004415 }
4416 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004417 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004418 }
4419 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4420}
4421
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004422sub mangle_symbol_MSVC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004423{
4424 my ($InfoId, $LibVersion) = @_;
4425 return "";
4426}
4427
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004428sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004429{ # see gcc-4.6.0/gcc/cp/mangle.c
4430 my ($InfoId, $LibVersion) = @_;
4431 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004432 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004433 my %Repl = ();# SN_ replacements
4434 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4435 {
4436 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4437 if($MangledClass!~/\AN/) {
4438 $MangledClass = "N".$MangledClass;
4439 }
4440 else {
4441 $MangledClass=~s/E\Z//;
4442 }
4443 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4444 $MangledClass=~s/\AN/NV/;
4445 }
4446 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4447 $MangledClass=~s/\AN/NK/;
4448 }
4449 $Mangled .= $MangledClass;
4450 }
4451 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4452 { # mangled by name due to the absence of structured info
4453 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4454 if($MangledNS!~/\AN/) {
4455 $MangledNS = "N".$MangledNS;
4456 }
4457 else {
4458 $MangledNS=~s/E\Z//;
4459 }
4460 $Mangled .= $MangledNS;
4461 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004462 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004463 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004464 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004465 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004466 foreach (@TPos) {
4467 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4468 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004469 }
4470 elsif($TmplParams)
4471 { # remangling mode
4472 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004473 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004474 }
4475 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4476 $Mangled .= "C1";
4477 }
4478 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4479 $Mangled .= "D0";
4480 }
4481 elsif($ShortName)
4482 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004483 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4484 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004485 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004486 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004487 { # "const" global data is mangled as _ZL...
4488 $Mangled .= "L";
4489 }
4490 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004491 if($ShortName=~/\Aoperator(\W.*)\Z/)
4492 {
4493 my $Op = $1;
4494 $Op=~s/\A[ ]+//g;
4495 if(my $OpMngl = $OperatorMangling{$Op}) {
4496 $Mangled .= $OpMngl;
4497 }
4498 else { # conversion operator
4499 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4500 }
4501 }
4502 else {
4503 $Mangled .= length($ShortName).$ShortName;
4504 }
4505 if(@TParams)
4506 { # templates
4507 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004508 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004509 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4510 }
4511 $Mangled .= "E";
4512 }
4513 if(not $ClassId and @TParams) {
4514 add_substitution($ShortName, \%Repl, 0);
4515 }
4516 }
4517 if($ClassId or $NameSpace) {
4518 $Mangled .= "E";
4519 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004520 if(@TParams)
4521 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004522 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004523 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4524 }
4525 }
4526 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4527 {
4528 my @Params = ();
4529 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4530 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4531 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4532 }
4533 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4534 { # checking parameters
4535 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4536 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4537 }
4538 if(not @Params) {
4539 $Mangled .= "v";
4540 }
4541 }
4542 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4543 $Mangled = write_stdcxx_substitution($Mangled);
4544 if($Mangled eq "_Z") {
4545 return "";
4546 }
4547 return $Mangled;
4548}
4549
4550sub correct_incharge($$$)
4551{
4552 my ($InfoId, $LibVersion, $Mangled) = @_;
4553 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4554 {
4555 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004556 $Mangled=~s/C1([EI])/C2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004557 }
4558 }
4559 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4560 {
4561 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004562 $Mangled=~s/D0([EI])/D1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004563 }
4564 if($MangledNames{$LibVersion}{$Mangled}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04004565 $Mangled=~s/D1([EI])/D2$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004566 }
4567 }
4568 return $Mangled;
4569}
4570
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004571sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004572{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004573 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004574 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004575 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004576 return $Name;
4577 }
4578 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004579 while(my $CPos = find_center($TParams, "<"))
4580 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004581 $TParams = substr($TParams, $CPos);
4582 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004583 if($TParams=~s/\A<(.+)>\Z/$1/) {
4584 $Name=~s/<\Q$TParams\E>\Z//;
4585 }
4586 else
4587 { # error
4588 $TParams = "";
4589 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004590 return ($Name, $TParams);
4591}
4592
4593sub get_sub_ns($)
4594{
4595 my $Name = $_[0];
4596 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004597 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004598 {
4599 push(@NS, substr($Name, 0, $CPos));
4600 $Name = substr($Name, $CPos);
4601 $Name=~s/\A:://;
4602 }
4603 return (join("::", @NS), $Name);
4604}
4605
4606sub mangle_ns($$$)
4607{
4608 my ($Name, $LibVersion, $Repl) = @_;
4609 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4610 {
4611 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4612 $Mangled=~s/\AN(.+)E\Z/$1/;
4613 return $Mangled;
4614
4615 }
4616 else
4617 {
4618 my ($MangledNS, $SubNS) = ("", "");
4619 ($SubNS, $Name) = get_sub_ns($Name);
4620 if($SubNS) {
4621 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4622 }
4623 $MangledNS .= length($Name).$Name;
4624 add_substitution($MangledNS, $Repl, 0);
4625 return $MangledNS;
4626 }
4627}
4628
4629sub mangle_param($$$)
4630{
4631 my ($PTid, $LibVersion, $Repl) = @_;
4632 my ($MPrefix, $Mangled) = ("", "");
4633 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004634 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004635 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004636 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004637 if(not $BaseType_Name) {
4638 return "";
4639 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004640 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004641 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004642 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4643 while($Suffix=~/(&|\*|const)\Z/)
4644 {
4645 if($Suffix=~s/[ ]*&\Z//) {
4646 $MPrefix .= "R";
4647 }
4648 if($Suffix=~s/[ ]*\*\Z//) {
4649 $MPrefix .= "P";
4650 }
4651 if($Suffix=~s/[ ]*const\Z//)
4652 {
4653 if($MPrefix=~/R|P/
4654 or $Suffix=~/&|\*/) {
4655 $MPrefix .= "K";
4656 }
4657 }
4658 if($Suffix=~s/[ ]*volatile\Z//) {
4659 $MPrefix .= "V";
4660 }
4661 #if($Suffix=~s/[ ]*restrict\Z//) {
4662 #$MPrefix .= "r";
4663 #}
4664 }
4665 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4666 $Mangled .= $Token;
4667 }
4668 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4669 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004670 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004671 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004672 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004673 foreach (@TPos) {
4674 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4675 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004676 }
4677 elsif($TmplParams)
4678 { # remangling mode
4679 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004680 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004681 }
4682 my $MangledNS = "";
4683 my ($SubNS, $SName) = get_sub_ns($ShortName);
4684 if($SubNS) {
4685 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4686 }
4687 $MangledNS .= length($SName).$SName;
4688 if(@TParams) {
4689 add_substitution($MangledNS, $Repl, 0);
4690 }
4691 $Mangled .= "N".$MangledNS;
4692 if(@TParams)
4693 { # templates
4694 $Mangled .= "I";
4695 foreach my $TParam (@TParams) {
4696 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4697 }
4698 $Mangled .= "E";
4699 }
4700 $Mangled .= "E";
4701 }
4702 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4703 {
4704 if($BaseType{"Type"} eq "MethodPtr") {
4705 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4706 }
4707 else {
4708 $Mangled .= "PF";
4709 }
4710 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4711 my @Params = keys(%{$BaseType{"Param"}});
4712 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4713 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4714 }
4715 if(not @Params) {
4716 $Mangled .= "v";
4717 }
4718 $Mangled .= "E";
4719 }
4720 elsif($BaseType{"Type"} eq "FieldPtr")
4721 {
4722 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4723 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4724 }
4725 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4726 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4727 {
4728 if($Mangled eq $Optimized)
4729 {
4730 if($ShortName!~/::/)
4731 { # remove "N ... E"
4732 if($MPrefix) {
4733 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4734 }
4735 else {
4736 $Mangled=~s/\AN(.+)E\Z/$1/g;
4737 }
4738 }
4739 }
4740 else {
4741 $Mangled = $Optimized;
4742 }
4743 }
4744 add_substitution($Mangled, $Repl, 1);
4745 return $Mangled;
4746}
4747
4748sub mangle_template_param($$$)
4749{ # types + literals
4750 my ($TParam, $LibVersion, $Repl) = @_;
4751 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4752 return mangle_param($TPTid, $LibVersion, $Repl);
4753 }
4754 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4755 { # class_name<1u>::method(...)
4756 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4757 }
4758 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4759 { # class_name<(signed char)1>::method(...)
4760 return "L".$IntrinsicMangling{$1}.$2."E";
4761 }
4762 elsif($TParam eq "true")
4763 { # class_name<true>::method(...)
4764 return "Lb1E";
4765 }
4766 elsif($TParam eq "false")
4767 { # class_name<true>::method(...)
4768 return "Lb0E";
4769 }
4770 else { # internal error
4771 return length($TParam).$TParam;
4772 }
4773}
4774
4775sub add_substitution($$$)
4776{
4777 my ($Value, $Repl, $Rec) = @_;
4778 if($Rec)
4779 { # subtypes
4780 my @Subs = ($Value);
4781 while($Value=~s/\A(R|P|K)//) {
4782 push(@Subs, $Value);
4783 }
4784 foreach (reverse(@Subs)) {
4785 add_substitution($_, $Repl, 0);
4786 }
4787 return;
4788 }
4789 return if($Value=~/\AS(\d*)_\Z/);
4790 $Value=~s/\AN(.+)E\Z/$1/g;
4791 return if(defined $Repl->{$Value});
4792 return if(length($Value)<=1);
4793 return if($StdcxxMangling{$Value});
4794 # check for duplicates
4795 my $Base = $Value;
4796 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4797 {
4798 my $Num = $Repl->{$Type};
4799 my $Replace = macro_mangle($Num);
4800 $Base=~s/\Q$Replace\E/$Type/;
4801 }
4802 if(my $OldNum = $Repl->{$Base})
4803 {
4804 $Repl->{$Value} = $OldNum;
4805 return;
4806 }
4807 my @Repls = sort {$b<=>$a} values(%{$Repl});
4808 if(@Repls) {
4809 $Repl->{$Value} = $Repls[0]+1;
4810 }
4811 else {
4812 $Repl->{$Value} = -1;
4813 }
4814 # register duplicates
4815 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004816 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004817 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4818 {
4819 next if($Base eq $Type);
4820 my $Num = $Repl->{$Type};
4821 my $Replace = macro_mangle($Num);
4822 $Base=~s/\Q$Type\E/$Replace/;
4823 $Repl->{$Base} = $Repl->{$Value};
4824 }
4825}
4826
4827sub macro_mangle($)
4828{
4829 my $Num = $_[0];
4830 if($Num==-1) {
4831 return "S_";
4832 }
4833 else
4834 {
4835 my $Code = "";
4836 if($Num<10)
4837 { # S0_, S1_, S2_, ...
4838 $Code = $Num;
4839 }
4840 elsif($Num>=10 and $Num<=35)
4841 { # SA_, SB_, SC_, ...
4842 $Code = chr(55+$Num);
4843 }
4844 else
4845 { # S10_, S11_, S12_
4846 $Code = $Num-26; # 26 is length of english alphabet
4847 }
4848 return "S".$Code."_";
4849 }
4850}
4851
4852sub write_stdcxx_substitution($)
4853{
4854 my $Mangled = $_[0];
4855 if($StdcxxMangling{$Mangled}) {
4856 return $StdcxxMangling{$Mangled};
4857 }
4858 else
4859 {
4860 my @Repls = keys(%StdcxxMangling);
4861 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4862 foreach my $MangledType (@Repls)
4863 {
4864 my $Replace = $StdcxxMangling{$MangledType};
4865 #if($Mangled!~/$Replace/) {
4866 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4867 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4868 #}
4869 }
4870 }
4871 return $Mangled;
4872}
4873
4874sub write_substitution($$)
4875{
4876 my ($Mangled, $Repl) = @_;
4877 if(defined $Repl->{$Mangled}
4878 and my $MnglNum = $Repl->{$Mangled}) {
4879 $Mangled = macro_mangle($MnglNum);
4880 }
4881 else
4882 {
4883 my @Repls = keys(%{$Repl});
4884 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4885 # FIXME: how to apply replacements? by num or by pos
4886 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4887 foreach my $MangledType (@Repls)
4888 {
4889 my $Replace = macro_mangle($Repl->{$MangledType});
4890 if($Mangled!~/$Replace/) {
4891 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4892 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4893 }
4894 }
4895 }
4896 return $Mangled;
4897}
4898
4899sub delete_keywords($)
4900{
4901 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004902 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004903 return $TypeName;
4904}
4905
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004906sub uncover_typedefs($$)
4907{
4908 my ($TypeName, $LibVersion) = @_;
4909 return "" if(not $TypeName);
4910 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4911 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4912 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004913 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004914 while($TypeName_New ne $TypeName_Pre)
4915 {
4916 $TypeName_Pre = $TypeName_New;
4917 my $TypeName_Copy = $TypeName_New;
4918 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004919 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004920 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004921 if(not $Intrinsic_Keywords{$1}) {
4922 $Words{$1} = 1;
4923 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004924 }
4925 foreach my $Word (keys(%Words))
4926 {
4927 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4928 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004929 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004930 if($BaseType_Name=~/\([\*]+\)/)
4931 { # FuncPtr
4932 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4933 {
4934 my $Type_Suffix = $1;
4935 $TypeName_New = $BaseType_Name;
4936 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004937 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004938 }
4939 }
4940 }
4941 else
4942 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004943 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004944 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004945 }
4946 }
4947 }
4948 }
4949 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4950}
4951
4952sub isInternal($)
4953{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004954 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4955 {
4956 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4957 {
4958 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4959 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4960 return 1;
4961 }
4962 }
4963 }
4964 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004965}
4966
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004967sub getDataVal($$)
4968{
4969 my ($InfoId, $TypeId) = @_;
4970 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4971 {
4972 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4973 {
4974 if(defined $LibInfo{$Version}{"info_type"}{$1}
4975 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004976 {
4977 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004978 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004979 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4980 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004981 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004982 if(my $Addr = getTreeAttr_Op($1)) {
4983 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004984 }
4985 }
4986 }
4987 }
4988 else {
4989 return getInitVal($1, $TypeId);
4990 }
4991 }
4992 }
4993 return undef;
4994}
4995
4996sub getInitVal($$)
4997{
4998 my ($InfoId, $TypeId) = @_;
4999 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
5000 {
5001 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
5002 {
5003 if($InfoType eq "integer_cst")
5004 {
5005 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005006 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005007 { # characters
5008 $Val = chr($Val);
5009 }
5010 return $Val;
5011 }
5012 elsif($InfoType eq "string_cst") {
5013 return getNodeStrCst($InfoId);
5014 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005015 elsif($InfoType eq "var_decl")
5016 {
5017 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
5018 return $Name;
5019 }
5020 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005021 }
5022 }
5023 return undef;
5024}
5025
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005026sub set_Class_And_Namespace($)
5027{
5028 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005029 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005030 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005031 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005032 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005033 my $NSInfoId = $1;
5034 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
5035 {
5036 if($InfoType eq "namespace_decl") {
5037 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
5038 }
5039 elsif($InfoType eq "record_type") {
5040 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
5041 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005042 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005043 }
5044 }
5045 if($SymbolInfo{$Version}{$InfoId}{"Class"}
5046 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005047 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005048 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005049 { # skip
5050 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005051 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005052 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005053
5054 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005055}
5056
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005057sub debugMangling($)
5058{
5059 my $LibVersion = $_[0];
5060 my %Mangled = ();
5061 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
5062 {
5063 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
5064 {
5065 if($Mngl=~/\A(_Z|\?)/) {
5066 $Mangled{$Mngl}=$InfoId;
5067 }
5068 }
5069 }
5070 translateSymbols(keys(%Mangled), $LibVersion);
5071 foreach my $Mngl (keys(%Mangled))
5072 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005073 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
5074 my $U2 = $tr_name{$Mngl};
5075 if($U1 ne $U2) {
5076 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005077 }
5078 }
5079}
5080
5081sub linkSymbol($)
5082{ # link symbols from shared libraries
5083 # with the symbols from header files
5084 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005085 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005086 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005087 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5088 or $EMERGENCY_MODE_48)
5089 { # GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
5090 # GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
5091 # GCC 4.8 doesn't mangle anything
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005092 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005093 {
5094 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
5095 return correct_incharge($InfoId, $Version, $Mangled);
5096 }
5097 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005098 if($CheckHeadersOnly
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005099 or not $BinaryOnly
5100 or $EMERGENCY_MODE_48)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005101 { # 1. --headers-only mode
5102 # 2. not mangled src-only symbols
5103 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
5104 return $Mangled;
5105 }
5106 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005107 }
5108 return "";
5109}
5110
5111sub setLanguage($$)
5112{
5113 my ($LibVersion, $Lang) = @_;
5114 if(not $UserLang) {
5115 $COMMON_LANGUAGE{$LibVersion} = $Lang;
5116 }
5117}
5118
5119sub getSymbolInfo($)
5120{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005121 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005122 if(isInternal($InfoId)) {
5123 return;
5124 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005125 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
5126 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005127 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
5128 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005129 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005130 return;
5131 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005132 setFuncAccess($InfoId);
5133 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005134 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
5135 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005136 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005137 return;
5138 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005139
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005140 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005141 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005142 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005143 if(not defined $TypeInfo{$Version}{$Return}
5144 or not $TypeInfo{$Version}{$Return}{"Name"})
5145 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005146 delete($SymbolInfo{$Version}{$InfoId});
5147 return;
5148 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005149 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005150 }
5151 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5152 {
5153 if(defined $MissedTypedef{$Version}{$Rid})
5154 {
5155 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5156 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5157 }
5158 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005159 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005160 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5161 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005162 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005163 my $Orig = getFuncOrig($InfoId);
5164 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005165 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5166 {
5167 delete($SymbolInfo{$Version}{$InfoId});
5168 return;
5169 }
5170
5171 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005172 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005173 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005174 return;
5175 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005176
5177 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005178 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005179 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5180
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005181 my @TParams = getTParams($Orig, "Func");
5182 if(not @TParams)
5183 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005184 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005185 return;
5186 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005187 foreach my $Pos (0 .. $#TParams)
5188 {
5189 my $Val = $TParams[$Pos];
5190 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5191
5192 if($Tmpl)
5193 {
5194 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5195 {
5196 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5197 }
5198 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005199 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005200
5201 if($Tmpl)
5202 {
5203 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5204 {
5205 if($Pos>$#TParams)
5206 {
5207 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5208 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5209 }
5210 }
5211 }
5212
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005213 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5214 { # operator<< <T>, operator>> <T>
5215 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5216 }
Andrey Ponomarenkob6a65ee2013-08-09 19:08:07 +04005217 if(@TParams) {
5218 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".join(", ", @TParams).">";
5219 }
5220 else {
5221 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<...>";
5222 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005223 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005224 }
5225 else
5226 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005227 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005228 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005229 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5230 {
5231 if($OSgroup eq "windows")
5232 { # cut the offset
5233 $MnglName=~s/\@\d+\Z//g;
5234 }
5235 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5236
5237 # NOTE: mangling of some symbols may change depending on GCC version
5238 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5239 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5240 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005241
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005242 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005243 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005244 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005245 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005246 return;
5247 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005248 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005249 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005250 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005251 if($Skip)
5252 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005253 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005254 return;
5255 }
5256 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005257 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5258 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5259 }
5260
5261 if(set_Class_And_Namespace($InfoId))
5262 {
5263 delete($SymbolInfo{$Version}{$InfoId});
5264 return;
5265 }
5266
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005267 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5268 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005269 if(not defined $TypeInfo{$Version}{$ClassId}
5270 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5271 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005272 delete($SymbolInfo{$Version}{$InfoId});
5273 return;
5274 }
5275 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005276 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5277 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005278 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005279 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005280 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005281 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005282 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005283 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005284 }
5285 if($COMMON_LANGUAGE{$Version} eq "C++")
5286 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005287 # C++ or --headers-only mode
5288 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005289 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005290 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5291 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005292 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005293 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005294 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005295 if(my $Mangled = linkSymbol($InfoId)) {
5296 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005297 }
5298 }
5299 if($OStarget eq "windows")
5300 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005301 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005302 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005303 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005304 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005305 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005306 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005307 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005308 }
5309 }
5310 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005311 else
5312 { # not mangled in C
5313 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5314 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005315 if(not $CheckHeadersOnly
5316 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5317 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5318 {
5319 my $Incorrect = 0;
5320
5321 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5322 {
5323 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5324 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5325 { # mangled in the TU dump, but not mangled in the library
5326 $Incorrect = 1;
5327 }
5328 }
5329 else
5330 {
5331 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5332 { # all C++ functions are not mangled in the TU dump
5333 $Incorrect = 1;
5334 }
5335 }
5336 if($Incorrect)
5337 {
5338 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5339 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5340 }
5341 }
5342 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005343 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005344 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005345 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005346 return;
5347 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005348 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005349 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005350 { # identify virtual and pure virtual functions
5351 # NOTE: constructors cannot be virtual
5352 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5353 # in the TU dump, so taking it from the original symbol
5354 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5355 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5356 { # NOTE: D2 destructors are not present in a v-table
5357 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5358 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005359 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005360 if(isInline($InfoId)) {
5361 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005362 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005363 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005364 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5365 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005366 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5367 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005368 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005369 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005370 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005371 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005372 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005373 }
5374 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005375 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5376 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005377 if(not $ExtraDump)
5378 {
5379 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5380 { # non-target symbols
5381 delete($SymbolInfo{$Version}{$InfoId});
5382 return;
5383 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005384 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005385 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005386 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5387 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5388 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5389 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005390 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005391 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5392 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005393 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005394 return;
5395 }
5396 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005397 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005398 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005399 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005400 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005401 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005402 return;
5403 }
5404 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005405 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005406 }
5407 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005408 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5409 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5410 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005411 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005412 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5413 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005414 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005415 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005416 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005417 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005418 }
5419 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005420 if(getFuncLink($InfoId) eq "Static") {
5421 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005422 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005423 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5424 {
5425 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5426 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005427 if($Unmangled=~/\.\_\d/)
5428 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005429 delete($SymbolInfo{$Version}{$InfoId});
5430 return;
5431 }
5432 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005433 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005434
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005435 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5436 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005437 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005438 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5439 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005440 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005441
5442 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5443 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5444 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005445
5446 if($ExtraDump) {
5447 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5448 }
5449}
5450
5451sub guessHeader($)
5452{
5453 my $InfoId = $_[0];
5454 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5455 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5456 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5457 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5458 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5459 {
5460 if(get_filename($HPath) eq $Header)
5461 {
5462 my $HDir = get_filename(get_dirname($HPath));
5463 if($HDir ne "include"
5464 and $HDir=~/\A[a-z]+\Z/i) {
5465 return join_P($HDir, $Header);
5466 }
5467 }
5468 }
5469 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005470}
5471
5472sub isInline($)
5473{ # "body: undefined" in the tree
5474 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005475 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5476 {
5477 if($Info=~/ undefined /i) {
5478 return 0;
5479 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005480 }
5481 return 1;
5482}
5483
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005484sub hasThrow($)
5485{
5486 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5487 {
5488 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5489 return getTreeAttr_Unql($1, "unql");
5490 }
5491 }
5492 return 1;
5493}
5494
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005495sub getTypeId($)
5496{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005497 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5498 {
5499 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5500 return $1;
5501 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005502 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005503 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005504}
5505
5506sub setTypeMemb($$)
5507{
5508 my ($TypeId, $TypeAttr) = @_;
5509 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005510 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005511 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005512 if($TypeType eq "Enum")
5513 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005514 my $MInfoId = getTreeAttr_Csts($TypeId);
5515 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005516 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005517 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5518 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005519 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005520 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5521 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005522 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005523 }
5524 }
5525 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5526 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005527 my $MInfoId = getTreeAttr_Flds($TypeId);
5528 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005529 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005530 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5531 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005532 if(not $IType or $IType ne "field_decl")
5533 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005534
5535 if($IType eq "var_decl")
5536 { # static field
5537 $StaticFields = 1;
5538 }
5539
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005540 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005541 next;
5542 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005543 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005544 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005545 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005546 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005547 }
5548 if(not $StructMembName)
5549 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005550 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005551 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005552 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005553 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5554 if(isAnon($UnnamedTName))
5555 { # rename unnamed fields to unnamed0, unnamed1, ...
5556 $StructMembName = "unnamed".($UnnamedPos++);
5557 }
5558 }
5559 }
5560 if(not $StructMembName)
5561 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005562 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005563 next;
5564 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005565 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005566 if(defined $MissedTypedef{$Version}{$MembTypeId})
5567 {
5568 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5569 $MembTypeId = $AddedTid;
5570 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005571 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005572
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005573 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5574 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005575 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005576 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005577 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5578 }
5579 if($MInfo=~/spec:\s*mutable /)
5580 { # mutable fields
5581 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005582 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005583 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005584 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5585 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005586 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005587 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005588 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005589 }
5590 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005591 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005592 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5593 { # template
5594 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5595 }
5596 else {
5597 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5598 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005599 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005600
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005601 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005602 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005603 }
5604 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005605
5606 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005607}
5608
5609sub setFuncParams($)
5610{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005611 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005612 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005613
5614 my $FType = getFuncType($InfoId);
5615
5616 if($FType eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005617 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005618 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5619 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005620 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005621 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005622 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5623 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005624 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005625 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5626 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005627 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005628 else
5629 { # skip
5630 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005631 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005632 # skip "this"-parameter
5633 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005634 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005635 my ($Pos, $PPos, $Vtt_Pos) = (0, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005636 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005637 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005638 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5639 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5640 if(not $ParamName)
5641 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005642 $ParamName = "p".($PPos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005643 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005644 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5645 {
5646 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5647 $ParamTypeId = $AddedTid;
5648 }
5649 }
5650 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005651 if(not $PType or $PType eq "Unknown") {
5652 return 1;
5653 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005654 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005655 if(not $PTName) {
5656 return 1;
5657 }
5658 if($PTName eq "void") {
5659 last;
5660 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005661 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005662 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005663 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005664 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005665 $ParamInfoId = getNextElem($ParamInfoId);
5666 next;
5667 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005668 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005669
5670 if(my %Base = get_BaseType($ParamTypeId, $Version))
5671 {
5672 if(defined $Base{"Template"}) {
5673 return 1;
5674 }
5675 }
5676
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005677 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005678 if(my $Algn = getAlgn($ParamInfoId)) {
5679 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5680 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005681 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5682 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005683 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005684 }
5685 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005686 $Pos += 1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005687 if($ParamName ne "this" or $FType ne "Method") {
5688 $PPos += 1;
5689 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005690 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005691 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005692 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005693 }
5694 return 0;
5695}
5696
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005697sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005698{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005699 my ($InfoId, $Vtt_Pos) = @_;
5700 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005701 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005702 my $FType = getFuncType($InfoId);
5703
5704 if($FType eq "Method")
5705 {
5706 # skip "this"-parameter
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005707 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005708 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005709 if(not $ParamListElemId)
5710 { # foo(...)
5711 return 1;
5712 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005713 my $HaveVoid = 0;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005714 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005715 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005716 { # actual params: may differ from formal args
5717 # formal int*const
5718 # actual: int*
5719 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005720 {
5721 $Vtt_Pos=-1;
5722 $ParamListElemId = getNextElem($ParamListElemId);
5723 next;
5724 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005725 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5726 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005727 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005728 $HaveVoid = 1;
5729 last;
5730 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005731 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005732 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005733 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5734 {
5735 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5736 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5737 { # unnamed
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005738 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($PPos+1);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005739 }
5740 }
5741 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5742 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005743 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005744 { # params
5745 if($OldId ne $ParamTypeId)
5746 {
5747 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5748 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5749
5750 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5751 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5752 }
5753 }
5754 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005755 }
5756 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005757 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005758 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005759 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5760 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005761 if($PurpType eq "nop_expr")
5762 { # func ( const char* arg = (const char*)(void*)0 )
5763 $PurpId = getTreeAttr_Op($PurpId);
5764 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005765 my $Val = getInitVal($PurpId, $ParamTypeId);
5766 if(defined $Val) {
5767 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5768 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005769 }
5770 }
5771 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04005772 if($Pos!=0 or $FType ne "Method") {
5773 $PPos += 1;
5774 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005775 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005776 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005777 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005778}
5779
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005780sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005781{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005782 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5783 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005784 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5785 return $1;
5786 }
5787 }
5788 return "";
5789}
5790
5791sub getTreeAttr_Chain($)
5792{
5793 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5794 {
5795 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5796 return $1;
5797 }
5798 }
5799 return "";
5800}
5801
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005802sub getTreeAttr_Unql($)
5803{
5804 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5805 {
5806 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5807 return $1;
5808 }
5809 }
5810 return "";
5811}
5812
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005813sub getTreeAttr_Scpe($)
5814{
5815 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5816 {
5817 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5818 return $1;
5819 }
5820 }
5821 return "";
5822}
5823
5824sub getTreeAttr_Type($)
5825{
5826 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5827 {
5828 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5829 return $1;
5830 }
5831 }
5832 return "";
5833}
5834
5835sub getTreeAttr_Name($)
5836{
5837 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5838 {
5839 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5840 return $1;
5841 }
5842 }
5843 return "";
5844}
5845
5846sub getTreeAttr_Mngl($)
5847{
5848 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5849 {
5850 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5851 return $1;
5852 }
5853 }
5854 return "";
5855}
5856
5857sub getTreeAttr_Prms($)
5858{
5859 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5860 {
5861 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5862 return $1;
5863 }
5864 }
5865 return "";
5866}
5867
5868sub getTreeAttr_Fncs($)
5869{
5870 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5871 {
5872 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5873 return $1;
5874 }
5875 }
5876 return "";
5877}
5878
5879sub getTreeAttr_Csts($)
5880{
5881 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5882 {
5883 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5884 return $1;
5885 }
5886 }
5887 return "";
5888}
5889
5890sub getTreeAttr_Purp($)
5891{
5892 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5893 {
5894 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5895 return $1;
5896 }
5897 }
5898 return "";
5899}
5900
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005901sub getTreeAttr_Op($)
5902{
5903 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5904 {
5905 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5906 return $1;
5907 }
5908 }
5909 return "";
5910}
5911
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005912sub getTreeAttr_Valu($)
5913{
5914 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5915 {
5916 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5917 return $1;
5918 }
5919 }
5920 return "";
5921}
5922
5923sub getTreeAttr_Flds($)
5924{
5925 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5926 {
5927 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5928 return $1;
5929 }
5930 }
5931 return "";
5932}
5933
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005934sub getTreeAttr_Binf($)
5935{
5936 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5937 {
5938 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5939 return $1;
5940 }
5941 }
5942 return "";
5943}
5944
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005945sub getTreeAttr_Args($)
5946{
5947 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5948 {
5949 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005950 return $1;
5951 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005952 }
5953 return "";
5954}
5955
5956sub getTreeValue($)
5957{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005958 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5959 {
5960 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5961 return $1;
5962 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005963 }
5964 return "";
5965}
5966
5967sub getTreeAccess($)
5968{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005969 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005970 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005971 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5972 {
5973 my $Access = $1;
5974 if($Access eq "prot") {
5975 return "protected";
5976 }
5977 elsif($Access eq "priv") {
5978 return "private";
5979 }
5980 }
5981 elsif($Info=~/ protected /)
5982 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005983 return "protected";
5984 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005985 elsif($Info=~/ private /)
5986 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005987 return "private";
5988 }
5989 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005990 return "public";
5991}
5992
5993sub setFuncAccess($)
5994{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005995 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005996 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005997 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005998 }
5999 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006000 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006001 }
6002}
6003
6004sub setTypeAccess($$)
6005{
6006 my ($TypeId, $TypeAttr) = @_;
6007 my $Access = getTreeAccess($TypeId);
6008 if($Access eq "protected") {
6009 $TypeAttr->{"Protected"} = 1;
6010 }
6011 elsif($Access eq "private") {
6012 $TypeAttr->{"Private"} = 1;
6013 }
6014}
6015
6016sub setFuncKind($)
6017{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006018 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6019 {
6020 if($Info=~/pseudo tmpl/) {
6021 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
6022 }
6023 elsif($Info=~/ constructor /) {
6024 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
6025 }
6026 elsif($Info=~/ destructor /) {
6027 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
6028 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006029 }
6030}
6031
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006032sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006033{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006034 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6035 {
6036 if($Info=~/spec[ ]*:[ ]*pure /) {
6037 return "PureVirt";
6038 }
6039 elsif($Info=~/spec[ ]*:[ ]*virt /) {
6040 return "Virt";
6041 }
6042 elsif($Info=~/ pure\s+virtual /)
6043 { # support for old GCC versions
6044 return "PureVirt";
6045 }
6046 elsif($Info=~/ virtual /)
6047 { # support for old GCC versions
6048 return "Virt";
6049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006050 }
6051 return "";
6052}
6053
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006054sub getFuncLink($)
6055{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006056 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6057 {
6058 if($Info=~/link[ ]*:[ ]*static /) {
6059 return "Static";
6060 }
6061 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006062 return $1;
6063 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006064 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006065 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006066}
6067
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006068sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006069{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006070 my ($Symbol, $LibVersion) = @_;
6071 return "" if(not $Symbol or not $LibVersion);
6072 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
6073 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006074 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006075 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
6076 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
6077 }
6078 }
6079 if($NS)
6080 {
6081 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6082 return $NS;
6083 }
6084 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006085 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006086 while($NS=~s/::[^:]+\Z//)
6087 {
6088 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6089 return $NS;
6090 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006091 }
6092 }
6093 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006094
6095 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006096}
6097
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006098sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006099{
6100 my ($TypeName, $LibVersion) = @_;
6101 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006102 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006103 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006104 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6105 return $NS;
6106 }
6107 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006108 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006109 while($NS=~s/::[^:]+\Z//)
6110 {
6111 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6112 return $NS;
6113 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006114 }
6115 }
6116 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006117 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006118}
6119
6120sub getNameSpace($)
6121{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006122 my $InfoId = $_[0];
6123 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006124 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006125 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006126 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006127 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006128 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006129 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
6130 {
6131 my $NameSpace = getTreeStr($1);
6132 if($NameSpace eq "::")
6133 { # global namespace
6134 return "";
6135 }
6136 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
6137 $NameSpace = $BaseNameSpace."::".$NameSpace;
6138 }
6139 $NestedNameSpaces{$Version}{$NameSpace} = 1;
6140 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006141 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006142 else {
6143 return "";
6144 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006145 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006146 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006147 { # inside data type
6148 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6149 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006150 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006151 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006152 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006153 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006154}
6155
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006156sub getEnumMembVal($)
6157{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006158 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006159 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006160 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6161 {
6162 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6163 {
6164 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6165 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6166 return getTreeValue($1);
6167 }
6168 else
6169 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6170 return getTreeValue($1);
6171 }
6172 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006173 }
6174 }
6175 return "";
6176}
6177
6178sub getSize($)
6179{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006180 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6181 {
6182 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6183 return getTreeValue($1);
6184 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006185 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006186 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006187}
6188
6189sub getAlgn($)
6190{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006191 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6192 {
6193 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6194 return $1;
6195 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006196 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006197 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006198}
6199
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006200sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006201{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006202 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6203 {
6204 if($Info=~/ bitfield /) {
6205 return getSize($_[0]);
6206 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006207 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006208 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006209}
6210
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006211sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006212{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006213 if(my $Chan = getTreeAttr_Chan($_[0])) {
6214 return $Chan;
6215 }
6216 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6217 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006218 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006219 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006220}
6221
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006222sub registerHeader($$)
6223{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006224 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006225 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006226 return "";
6227 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006228 if(is_abs($Header) and not -f $Header)
6229 { # incorrect absolute path
6230 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006231 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006232 if(skipHeader($Header, $LibVersion))
6233 { # skip
6234 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006235 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006236 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6237 {
6238 detect_header_includes($Header_Path, $LibVersion);
6239
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006240 if(defined $Tolerance and $Tolerance=~/3/)
6241 { # 3 - skip headers that include non-Linux headers
6242 if($OSgroup ne "windows")
6243 {
6244 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6245 {
6246 if(specificHeader($Inc, "windows")) {
6247 return "";
6248 }
6249 }
6250 }
6251 }
6252
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006253 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6254 { # redirect
6255 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6256 or skipHeader($RHeader_Path, $LibVersion))
6257 { # skip
6258 return "";
6259 }
6260 $Header_Path = $RHeader_Path;
6261 }
6262 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6263 { # skip
6264 return "";
6265 }
6266
6267 if(my $HName = get_filename($Header_Path))
6268 { # register
6269 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6270 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6271 }
6272
6273 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6274 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006275 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006276 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006277 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006278 }
6279
6280 if($CheckHeadersOnly
6281 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6282 { # /usr/include/c++/4.6.1/...
6283 $STDCXX_TESTING = 1;
6284 }
6285
6286 return $Header_Path;
6287 }
6288 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006289}
6290
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006291sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006292{
6293 my ($Dir, $WithDeps, $LibVersion) = @_;
6294 $Dir=~s/[\/\\]+\Z//g;
6295 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006296 $Dir = get_abs_path($Dir);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04006297
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006298 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006299 if($WithDeps)
6300 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006301 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6302 return;
6303 }
6304 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6305 $Mode = "DepsOnly";
6306 }
6307 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006308 else
6309 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006310 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6311 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6312 return;
6313 }
6314 }
6315 $Header_Dependency{$LibVersion}{$Dir} = 1;
6316 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6317 if($Mode eq "DepsOnly")
6318 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006319 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006320 $Header_Dependency{$LibVersion}{$Path} = 1;
6321 }
6322 return;
6323 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006324 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006325 {
6326 if($WithDeps)
6327 {
6328 my $SubDir = $Path;
6329 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6330 { # register all sub directories
6331 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6332 }
6333 }
6334 next if(is_not_header($Path));
6335 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006336 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006337 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006338 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6339 }
6340 }
6341 if(get_filename($Dir) eq "include")
6342 { # search for "lib/include/" directory
6343 my $LibDir = $Dir;
6344 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006345 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006346 }
6347 }
6348}
6349
6350sub parse_redirect($$$)
6351{
6352 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006353 my @Errors = ();
6354 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6355 push(@Errors, $1);
6356 }
6357 my $Redirect = "";
6358 foreach (@Errors)
6359 {
6360 s/\s{2,}/ /g;
6361 if(/(only|must\ include
6362 |update\ to\ include
6363 |replaced\ with
6364 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006365 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006366 {
6367 $Redirect = $2;
6368 last;
6369 }
6370 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6371 {
6372 $Redirect = $2;
6373 last;
6374 }
6375 elsif(/this\ header\ should\ not\ be\ used
6376 |programs\ should\ not\ directly\ include
6377 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6378 |is\ not\ supported\ API\ for\ general\ use
6379 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006380 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006381 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6382 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6383 }
6384 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006385 if($Redirect)
6386 {
6387 $Redirect=~s/\A<//g;
6388 $Redirect=~s/>\Z//g;
6389 }
6390 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006391}
6392
6393sub parse_includes($$)
6394{
6395 my ($Content, $Path) = @_;
6396 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006397 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006398 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006399 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006400 my $Method = substr($Header, 0, 1, "");
6401 substr($Header, length($Header)-1, 1, "");
6402 $Header = path_format($Header, $OSgroup);
6403 if($Method eq "\"" or is_abs($Header))
6404 {
6405 if(-e join_P(get_dirname($Path), $Header))
6406 { # relative path exists
6407 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006408 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006409 else
6410 { # include "..." that doesn't exist is equal to include <...>
6411 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006412 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006413 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006414 else {
6415 $Includes{$Header} = 1;
6416 }
6417 }
6418 if($ExtraInfo)
6419 {
6420 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6421 { # FT_FREETYPE_H
6422 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006423 }
6424 }
6425 return \%Includes;
6426}
6427
6428sub ignore_path($)
6429{
6430 my $Path = $_[0];
6431 if($Path=~/\~\Z/)
6432 {# skipping system backup files
6433 return 1;
6434 }
6435 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6436 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6437 return 1;
6438 }
6439 return 0;
6440}
6441
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006442sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006443{
6444 my ($ArrRef, $W) = @_;
6445 return if(length($W)<2);
6446 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6447}
6448
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006449sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006450{
6451 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006452
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006453 $H1=~s/\.[a-z]+\Z//ig;
6454 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006455
6456 my $Hname1 = get_filename($H1);
6457 my $Hname2 = get_filename($H2);
6458 my $HDir1 = get_dirname($H1);
6459 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006460 my $Dirname1 = get_filename($HDir1);
6461 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006462
6463 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6464 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6465
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006466 if($_[0] eq $_[1]
6467 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006468 return 0;
6469 }
6470 elsif($H1=~/\A\Q$H2\E/) {
6471 return 1;
6472 }
6473 elsif($H2=~/\A\Q$H1\E/) {
6474 return -1;
6475 }
6476 elsif($HDir1=~/\Q$Hname1\E/i
6477 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006478 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006479 return -1;
6480 }
6481 elsif($HDir2=~/\Q$Hname2\E/i
6482 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006483 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006484 return 1;
6485 }
6486 elsif($Hname1=~/\Q$Dirname1\E/i
6487 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006488 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006489 return -1;
6490 }
6491 elsif($Hname2=~/\Q$Dirname2\E/i
6492 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006493 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006494 return 1;
6495 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006496 elsif($Hname1=~/(config|lib|util)/i
6497 and $Hname2!~/(config|lib|util)/i)
6498 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006499 return -1;
6500 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006501 elsif($Hname2=~/(config|lib|util)/i
6502 and $Hname1!~/(config|lib|util)/i)
6503 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006504 return 1;
6505 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006506 else
6507 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006508 my $R1 = checkRelevance($H1);
6509 my $R2 = checkRelevance($H2);
6510 if($R1 and not $R2)
6511 { # libebook/e-book.h
6512 return -1;
6513 }
6514 elsif($R2 and not $R1)
6515 { # libebook/e-book.h
6516 return 1;
6517 }
6518 else
6519 {
6520 return (lc($H1) cmp lc($H2));
6521 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006522 }
6523}
6524
6525sub searchForHeaders($)
6526{
6527 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006528
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006529 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006530 registerGccHeaders();
6531
6532 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6533 { # c++ standard include paths
6534 registerCppHeaders();
6535 }
6536
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006537 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006538 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6539 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006540 {
6541 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006542 if($SystemRoot)
6543 {
6544 if(is_abs($Path)) {
6545 $Path = $SystemRoot.$Path;
6546 }
6547 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006548 if(not -e $Path) {
6549 exitStatus("Access_Error", "can't access \'$Path\'");
6550 }
6551 elsif(-f $Path) {
6552 exitStatus("Access_Error", "\'$Path\' - not a directory");
6553 }
6554 elsif(-d $Path)
6555 {
6556 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006557 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006558 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6559 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006560 }
6561 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006562 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006563 }
6564 }
6565 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006566 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006567 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6568 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006569
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006570 # registering directories
6571 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6572 {
6573 next if(not -e $Path);
6574 $Path = get_abs_path($Path);
6575 $Path = path_format($Path, $OSgroup);
6576 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006577 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006578 }
6579 elsif(-f $Path)
6580 {
6581 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006582 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006583 and not $LocalIncludes{$Dir})
6584 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006585 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006586 # if(my $OutDir = get_dirname($Dir))
6587 # { # registering the outer directory
6588 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6589 # and not $LocalIncludes{$OutDir}) {
6590 # registerDir($OutDir, 0, $LibVersion);
6591 # }
6592 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006593 }
6594 }
6595 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006596
6597 # clean memory
6598 %RegisteredDirs = ();
6599
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006600 # registering headers
6601 my $Position = 0;
6602 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6603 {
6604 if(is_abs($Dest) and not -e $Dest) {
6605 exitStatus("Access_Error", "can't access \'$Dest\'");
6606 }
6607 $Dest = path_format($Dest, $OSgroup);
6608 if(is_header($Dest, 1, $LibVersion))
6609 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006610 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006611 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6612 }
6613 }
6614 elsif(-d $Dest)
6615 {
6616 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006617 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006618 {
6619 next if(ignore_path($Path));
6620 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006621 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006622 push(@Registered, $HPath);
6623 }
6624 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006625 @Registered = sort {sortHeaders($a, $b)} @Registered;
6626 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006627 foreach my $Path (@Registered) {
6628 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6629 }
6630 }
6631 else {
6632 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6633 }
6634 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006635
6636 if(defined $Tolerance and $Tolerance=~/4/)
6637 { # 4 - skip headers included by others
6638 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6639 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006640 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006641 delete($Registered_Headers{$LibVersion}{$Path});
6642 }
6643 }
6644 }
6645
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006646 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6647 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006648 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006649 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006650 if(is_abs($Header) and not -f $Header) {
6651 exitStatus("Access_Error", "can't access file \'$Header\'");
6652 }
6653 $Header = path_format($Header, $OSgroup);
6654 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6655 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006656 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006657 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006658 }
6659 else {
6660 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6661 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006662 }
6663 }
6664 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6665 { # set relative paths (for duplicates)
6666 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6667 { # search for duplicates
6668 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6669 my $Prefix = get_dirname($FirstPath);
6670 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6671 { # detect a shortest distinguishing prefix
6672 my $NewPrefix = $1;
6673 my %Identity = ();
6674 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6675 {
6676 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6677 $Identity{$Path} = $1;
6678 }
6679 }
6680 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6681 { # all names are differend with current prefix
6682 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6683 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6684 }
6685 last;
6686 }
6687 $Prefix = $NewPrefix; # increase prefix
6688 }
6689 }
6690 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006691
6692 # clean memory
6693 %HeaderName_Paths = ();
6694
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006695 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6696 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006697 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006698 my ($Pos, $PairPos) = (-1, -1);
6699 my ($Path, $PairPath) = ();
6700 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6701 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6702 foreach my $Header_Path (@Paths)
6703 {
6704 if(get_filename($Header_Path) eq $PairName)
6705 {
6706 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6707 $PairPath = $Header_Path;
6708 }
6709 if(get_filename($Header_Path) eq $HeaderName)
6710 {
6711 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6712 $Path = $Header_Path;
6713 }
6714 }
6715 if($PairPos!=-1 and $Pos!=-1
6716 and int($PairPos)<int($Pos))
6717 {
6718 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6719 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6720 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6721 }
6722 }
6723 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6724 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6725 }
6726}
6727
6728sub detect_real_includes($$)
6729{
6730 my ($AbsPath, $LibVersion) = @_;
6731 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6732 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6733 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6734 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6735 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006736 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6737
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006738 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6739 return () if(not $Path);
6740 open(PREPROC, $Path);
6741 while(<PREPROC>)
6742 {
6743 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6744 {
6745 my $Include = path_format($1, $OSgroup);
6746 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6747 next;
6748 }
6749 if($Include eq $AbsPath) {
6750 next;
6751 }
6752 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6753 }
6754 }
6755 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006756 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6757}
6758
6759sub detect_header_includes($$)
6760{
6761 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006762 return if(not $LibVersion or not $Path);
6763 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6764 return;
6765 }
6766 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6767
6768 if(not -e $Path) {
6769 return;
6770 }
6771
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006772 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006773 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6774 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006775 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006776 {
6777 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006778 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006779 }
6780 if($RedirectPath ne $Path) {
6781 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6782 }
6783 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006784 else
6785 { # can't find
6786 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6787 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006788 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006789 if(my $Inc = parse_includes($Content, $Path))
6790 {
6791 foreach my $Include (keys(%{$Inc}))
6792 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006793 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006794
6795 if(defined $Tolerance and $Tolerance=~/4/)
6796 {
6797 if(my $HPath = identifyHeader($Include, $LibVersion))
6798 {
6799 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6800 }
6801 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006802 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006803 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006804}
6805
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006806sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006807{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006808 my $Path = $_[0];
6809 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006810 if($OStarget eq "symbian")
6811 {
6812 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6813 { # epoc32/include/libc/{stdio, ...}.h
6814 return 1;
6815 }
6816 }
6817 else
6818 {
6819 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6820 { # /usr/include/{stdio, ...}.h
6821 return 1;
6822 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006823 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006824 return 0;
6825}
6826
6827sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006828{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006829 my $Dir = $_[0];
6830 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006831 if($OStarget eq "symbian")
6832 {
6833 if(get_filename($OutDir) eq "libc"
6834 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6835 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6836 return 1;
6837 }
6838 }
6839 else
6840 { # linux
6841 if($OutDir eq "/usr/include"
6842 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6843 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6844 return 1;
6845 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006846 }
6847 return 0;
6848}
6849
6850sub detect_recursive_includes($$)
6851{
6852 my ($AbsPath, $LibVersion) = @_;
6853 return () if(not $AbsPath);
6854 if(isCyclical(\@RecurInclude, $AbsPath)) {
6855 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6856 }
6857 my ($AbsDir, $Name) = separate_path($AbsPath);
6858 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006859 { # system GLIBC internals
6860 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006861 }
6862 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6863 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6864 }
6865 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006866
6867 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6868 { # skip /usr/include/c++/*/ headers
6869 return () if(not $ExtraInfo);
6870 }
6871
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006872 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006873 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006874 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006875 { # check "real" (non-"model") include paths
6876 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6877 pop(@RecurInclude);
6878 return @Paths;
6879 }
6880 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6881 detect_header_includes($AbsPath, $LibVersion);
6882 }
6883 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6884 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006885 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006886 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006887 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006888 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006889 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006890 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006891 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006892 }
6893 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006894 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006895 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006896 { # search for the nearest header
6897 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006898 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006899 if(-f $Candidate) {
6900 $HPath = $Candidate;
6901 }
6902 }
6903 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006904 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006905 }
6906 next if(not $HPath);
6907 if($HPath eq $AbsPath) {
6908 next;
6909 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006910
6911 if($Debug)
6912 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006913# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6914# {
6915# print STDERR "$AbsPath -> $HPath\n";
6916# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006917 }
6918
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006919 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6920 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006921 { # only include <...>, skip include "..." prefixes
6922 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6923 }
6924 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6925 {
6926 if($IncPath eq $AbsPath) {
6927 next;
6928 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006929 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6930 if($RIncType==-1)
6931 { # include "..."
6932 $RIncType = $IncType;
6933 }
6934 elsif($RIncType==2)
6935 {
6936 if($IncType!=-1) {
6937 $RIncType = $IncType;
6938 }
6939 }
6940 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006941 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6942 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6943 }
6944 }
6945 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6946 {
6947 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6948 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6949 { # distinguish math.h from glibc and math.h from the tested library
6950 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6951 last;
6952 }
6953 }
6954 }
6955 pop(@RecurInclude);
6956 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6957}
6958
6959sub find_in_framework($$$)
6960{
6961 my ($Header, $Framework, $LibVersion) = @_;
6962 return "" if(not $Header or not $Framework or not $LibVersion);
6963 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6964 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6965 }
6966 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6967 {
6968 if(get_filename($Dependency) eq $Framework
6969 and -f get_dirname($Dependency)."/".$Header) {
6970 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6971 }
6972 }
6973 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6974}
6975
6976sub find_in_defaults($)
6977{
6978 my $Header = $_[0];
6979 return "" if(not $Header);
6980 if(defined $Cache{"find_in_defaults"}{$Header}) {
6981 return $Cache{"find_in_defaults"}{$Header};
6982 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006983 foreach my $Dir (@DefaultIncPaths,
6984 @DefaultGccPaths,
6985 @DefaultCppPaths,
6986 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006987 {
6988 next if(not $Dir);
6989 if(-f $Dir."/".$Header) {
6990 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6991 }
6992 }
6993 return ($Cache{"find_in_defaults"}{$Header}="");
6994}
6995
6996sub cmp_paths($$)
6997{
6998 my ($Path1, $Path2) = @_;
6999 my @Parts1 = split(/[\/\\]/, $Path1);
7000 my @Parts2 = split(/[\/\\]/, $Path2);
7001 foreach my $Num (0 .. $#Parts1)
7002 {
7003 my $Part1 = $Parts1[$Num];
7004 my $Part2 = $Parts2[$Num];
7005 if($GlibcDir{$Part1}
7006 and not $GlibcDir{$Part2}) {
7007 return 1;
7008 }
7009 elsif($GlibcDir{$Part2}
7010 and not $GlibcDir{$Part1}) {
7011 return -1;
7012 }
7013 elsif($Part1=~/glib/
7014 and $Part2!~/glib/) {
7015 return 1;
7016 }
7017 elsif($Part1!~/glib/
7018 and $Part2=~/glib/) {
7019 return -1;
7020 }
7021 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
7022 return $CmpRes;
7023 }
7024 }
7025 return 0;
7026}
7027
7028sub checkRelevance($)
7029{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007030 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007031 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007032
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007033 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007034 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007035 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007036
7037 my $Name = lc(get_filename($Path));
7038 my $Dir = lc(get_dirname($Path));
7039
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007040 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007041
7042 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007043 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007044 my $Len = length($Token);
7045 next if($Len<=1);
7046 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
7047 { # include/evolution-data-server-1.4/libebook/e-book.h
7048 return 1;
7049 }
7050 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007051 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007052 return 1;
7053 }
7054 }
7055 return 0;
7056}
7057
7058sub checkFamily(@)
7059{
7060 my @Paths = @_;
7061 return 1 if($#Paths<=0);
7062 my %Prefix = ();
7063 foreach my $Path (@Paths)
7064 {
7065 if($SystemRoot) {
7066 $Path = cut_path_prefix($Path, $SystemRoot);
7067 }
7068 if(my $Dir = get_dirname($Path))
7069 {
7070 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
7071 $Prefix{$Dir} += 1;
7072 $Prefix{get_dirname($Dir)} += 1;
7073 }
7074 }
7075 foreach (sort keys(%Prefix))
7076 {
7077 if(get_depth($_)>=3
7078 and $Prefix{$_}==$#Paths+1) {
7079 return 1;
7080 }
7081 }
7082 return 0;
7083}
7084
7085sub isAcceptable($$$)
7086{
7087 my ($Header, $Candidate, $LibVersion) = @_;
7088 my $HName = get_filename($Header);
7089 if(get_dirname($Header))
7090 { # with prefix
7091 return 1;
7092 }
7093 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
7094 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
7095 return 1;
7096 }
7097 if(checkRelevance($Candidate))
7098 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
7099 return 1;
7100 }
7101 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
7102 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
7103 # /usr/include/qt4/Qt/qsslconfiguration.h
7104 return 1;
7105 }
7106 if($OStarget eq "symbian")
7107 {
7108 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
7109 return 1;
7110 }
7111 }
7112 return 0;
7113}
7114
7115sub isRelevant($$$)
7116{ # disallow to search for "abstract" headers in too deep directories
7117 my ($Header, $Candidate, $LibVersion) = @_;
7118 my $HName = get_filename($Header);
7119 if($OStarget eq "symbian")
7120 {
7121 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
7122 return 0;
7123 }
7124 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007125 if($OStarget ne "bsd")
7126 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007127 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
7128 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
7129 return 0;
7130 }
7131 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007132 if($OStarget ne "windows")
7133 {
7134 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
7135 { # skip /usr/include/wine/msvcrt
7136 return 0;
7137 }
7138 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007139 if(not get_dirname($Header)
7140 and $Candidate=~/[\/\\]wx[\/\\]/)
7141 { # do NOT search in system /wx/ directory
7142 # for headers without a prefix: sstream.h
7143 return 0;
7144 }
7145 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7146 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7147 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7148 return 0;
7149 }
7150 if($Candidate=~/[\/\\]asm-/
7151 and (my $Arch = getArch($LibVersion)) ne "unknown")
7152 { # arch-specific header files
7153 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7154 {# skip ../asm-arm/ if using x86 architecture
7155 return 0;
7156 }
7157 }
7158 my @Candidates = getSystemHeaders($HName, $LibVersion);
7159 if($#Candidates==1)
7160 { # unique header
7161 return 1;
7162 }
7163 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7164 if($#SCandidates==1)
7165 { # unique name
7166 return 1;
7167 }
7168 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7169 if(get_depth($Candidate)-$SystemDepth>=5)
7170 { # abstract headers in too deep directories
7171 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7172 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7173 return 0;
7174 }
7175 }
7176 if($Header eq "parser.h"
7177 and $Candidate!~/\/libxml2\//)
7178 { # select parser.h from xml2 library
7179 return 0;
7180 }
7181 if(not get_dirname($Header)
7182 and keys(%{$SystemHeaders{$HName}})>=3)
7183 { # many headers with the same name
7184 # like thread.h included without a prefix
7185 if(not checkFamily(@Candidates)) {
7186 return 0;
7187 }
7188 }
7189 return 1;
7190}
7191
7192sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007193{ # cache function
7194 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7195 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7196 }
7197 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7198}
7199
7200sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007201{
7202 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007203 if(-f $Header) {
7204 return $Header;
7205 }
7206 if(is_abs($Header) and not -f $Header)
7207 { # incorrect absolute path
7208 return "";
7209 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007210 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007211 { # too abstract configuration headers
7212 return "";
7213 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007214 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007215 if($OSgroup ne "windows")
7216 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007217 if(defined $WinHeaders{lc($HName)}
7218 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007219 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007220 return "";
7221 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007222 }
7223 if($OSgroup ne "macos")
7224 {
7225 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007226 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007227 return "";
7228 }
7229 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007230
7231 if(defined $ObsoleteHeaders{$HName})
7232 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007233 return "";
7234 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007235 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7236 {
7237 if(defined $AlienHeaders{$HName}
7238 or defined $AlienHeaders{$Header})
7239 { # alien headers from other systems
7240 return "";
7241 }
7242 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007243
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007244 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007245 { # search in default paths
7246 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007247 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007248 }
7249 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007250 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007251 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007252 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007253 }
7254 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7255 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7256 {
7257 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007258 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007259 }
7260 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007261 # error
7262 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007263}
7264
7265sub getSystemHeaders($$)
7266{
7267 my ($Header, $LibVersion) = @_;
7268 my @Candidates = ();
7269 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7270 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007271 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007272 next;
7273 }
7274 push(@Candidates, $Candidate);
7275 }
7276 return @Candidates;
7277}
7278
7279sub cut_path_prefix($$)
7280{
7281 my ($Path, $Prefix) = @_;
7282 return $Path if(not $Prefix);
7283 $Prefix=~s/[\/\\]+\Z//;
7284 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7285 return $Path;
7286}
7287
7288sub is_default_include_dir($)
7289{
7290 my $Dir = $_[0];
7291 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007292 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007293}
7294
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007295sub identifyHeader($$)
7296{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007297 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007298 if(not $Header) {
7299 return "";
7300 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007301 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007302 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7303 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007304 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007305 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007306}
7307
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007308sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007309{ # search for header by absolute path, relative path or name
7310 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007311 if(-f $Header)
7312 { # it's relative or absolute path
7313 return get_abs_path($Header);
7314 }
7315 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7316 and my $HeaderDir = find_in_defaults($Header))
7317 { # search for libc headers in the /usr/include
7318 # for non-libc target library before searching
7319 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007320 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007321 }
7322 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7323 { # search in the target library paths
7324 return $Path;
7325 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007326 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007327 { # search in the internal GCC include paths
7328 return $DefaultGccHeader{$Header};
7329 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007330 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007331 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007332 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007333 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007334 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007335 { # search in the default G++ include paths
7336 return $DefaultCppHeader{$Header};
7337 }
7338 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7339 { # search everywhere in the system
7340 return $AnyPath;
7341 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007342 elsif($OSgroup eq "macos")
7343 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7344 if(my $Dir = get_dirname($Header))
7345 {
7346 my $RelPath = "Headers\/".get_filename($Header);
7347 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007348 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007349 }
7350 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007351 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007352 # cannot find anything
7353 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007354}
7355
7356sub getLocation($)
7357{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007358 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7359 {
7360 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007361 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007362 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007363 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007364 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007365}
7366
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007367sub getNameByInfo($)
7368{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007369 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007370 {
7371 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7372 {
7373 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7374 {
7375 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7376 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007377 my $Str = $1;
7378 if($CppMode{$Version}
7379 and $Str=~/\Ac99_(.+)\Z/)
7380 {
7381 if($CppKeywords_A{$1}) {
7382 $Str=$1;
7383 }
7384 }
7385 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007386 }
7387 }
7388 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007389 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007390 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007391}
7392
7393sub getTreeStr($)
7394{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007395 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007396 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007397 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7398 {
7399 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007400 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007401 and $Str=~/\Ac99_(.+)\Z/)
7402 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007403 if($CppKeywords_A{$1}) {
7404 $Str=$1;
7405 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007406 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007407 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007408 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007409 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007410 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007411}
7412
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007413sub getFuncShortName($)
7414{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007415 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007416 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007417 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007418 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007419 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007420 {
7421 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7422 {
7423 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7424 return "operator ".$RName;
7425 }
7426 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007427 }
7428 else
7429 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007430 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7431 {
7432 if(my $Ind = $Operator_Indication{$1}) {
7433 return "operator".$Ind;
7434 }
7435 elsif(not $UnknownOperator{$1})
7436 {
7437 printMsg("WARNING", "unknown operator $1");
7438 $UnknownOperator{$1} = 1;
7439 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007440 }
7441 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007442 }
7443 else
7444 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007445 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7446 return getTreeStr($1);
7447 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007448 }
7449 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007450 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007451}
7452
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007453sub getFuncReturn($)
7454{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007455 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7456 {
7457 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7458 {
7459 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7460 return $1;
7461 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007462 }
7463 }
7464 return "";
7465}
7466
7467sub getFuncOrig($)
7468{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007469 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7470 {
7471 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7472 return $1;
7473 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007474 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007475 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007476}
7477
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007478sub unmangleArray(@)
7479{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007480 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007481 { # MSVC mangling
7482 my $UndNameCmd = get_CmdPath("undname");
7483 if(not $UndNameCmd) {
7484 exitStatus("Not_Found", "can't find \"undname\"");
7485 }
7486 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007487 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007488 }
7489 else
7490 { # GCC mangling
7491 my $CppFiltCmd = get_CmdPath("c++filt");
7492 if(not $CppFiltCmd) {
7493 exitStatus("Not_Found", "can't find c++filt in PATH");
7494 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007495 if(not defined $CPPFILT_SUPPORT_FILE)
7496 {
7497 my $Info = `$CppFiltCmd -h 2>&1`;
7498 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7499 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007500 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007501 if($CPPFILT_SUPPORT_FILE)
7502 { # new versions of c++filt can take a file
7503 if($#_>$MAX_CPPFILT_FILE_SIZE)
7504 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7505 # this is fixed in the oncoming version of Binutils
7506 my @Half = splice(@_, 0, ($#_+1)/2);
7507 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007508 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007509 else
7510 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007511 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7512 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7513 if($?==139)
7514 { # segmentation fault
7515 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7516 }
7517 return split(/\n/, $Res);
7518 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007519 }
7520 else
7521 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007522 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7523 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007524 my @Half = splice(@_, 0, ($#_+1)/2);
7525 return (unmangleArray(@Half), unmangleArray(@_))
7526 }
7527 else
7528 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007529 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007530 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7531 if($?==139)
7532 { # segmentation fault
7533 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7534 }
7535 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007536 }
7537 }
7538 }
7539}
7540
7541sub get_SignatureNoInfo($$)
7542{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007543 my ($Symbol, $LibVersion) = @_;
7544 if($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol}) {
7545 return $Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007546 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007547 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007548 my $Signature = $tr_name{$MnglName}?$tr_name{$MnglName}:$MnglName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007549 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007550 { # C++
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04007551 # some standard typedefs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007552 $Signature=~s/\Qstd::basic_string<char, std::char_traits<char>, std::allocator<char> >\E/std::string/g;
7553 $Signature=~s/\Qstd::map<std::string, std::string, std::less<std::string >, std::allocator<std::pair<std::string const, std::string > > >\E/std::map<std::string, std::string>/g;
7554 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007555 if(not $CheckObjectsOnly or $OSgroup=~/linux|bsd|beos/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007556 { # ELF format marks data as OBJECT
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007557 if($GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007558 $Signature .= " [data]";
7559 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007560 elsif($Symbol!~/\A(_Z|\?)/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007561 $Signature .= " (...)";
7562 }
7563 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007564 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007565 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04007566 my $ShortName = substr($Signature, 0, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007567 $Signature=~s/\A\Q$ShortName\E/$ShortName $ChargeLevel/g;
7568 }
7569 if($SymbolVersion) {
7570 $Signature .= $VersionSpec.$SymbolVersion;
7571 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007572 return ($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007573}
7574
7575sub get_ChargeLevel($$)
7576{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007577 my ($Symbol, $LibVersion) = @_;
7578 return "" if($Symbol!~/\A(_Z|\?)/);
7579 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7580 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007581 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007582 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007583 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007584 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007585 return "[in-charge]";
7586 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007587 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007588 return "[not-in-charge]";
7589 }
7590 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007591 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007592 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007593 if($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007594 return "[in-charge]";
7595 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007596 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007597 return "[not-in-charge]";
7598 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007599 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007600 return "[in-charge-deleting]";
7601 }
7602 }
7603 }
7604 else
7605 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007606 if($Symbol=~/C1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007607 return "[in-charge]";
7608 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007609 elsif($Symbol=~/C2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007610 return "[not-in-charge]";
7611 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007612 elsif($Symbol=~/D1[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007613 return "[in-charge]";
7614 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007615 elsif($Symbol=~/D2[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007616 return "[not-in-charge]";
7617 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007618 elsif($Symbol=~/D0[EI]/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007619 return "[in-charge-deleting]";
7620 }
7621 }
7622 return "";
7623}
7624
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007625sub get_Signature_M($$)
7626{
7627 my ($Symbol, $LibVersion) = @_;
7628 my $Signature_M = $tr_name{$Symbol};
7629 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7630 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007631 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007632 }
7633 return $Signature_M;
7634}
7635
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007636sub get_Signature($$)
7637{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007638 my ($Symbol, $LibVersion) = @_;
7639 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7640 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007641 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007642 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
7643 if(isPrivateData($MnglName) or not $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007644 { # non-public global data
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007645 return get_SignatureNoInfo($Symbol, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007646 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007647 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007648 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7649 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007650 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007651 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7652 {
7653 $Signature .= $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::";
7654 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7655 $Signature .= "~";
7656 }
7657 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007658 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007659 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007660 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007661 }
7662 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007663 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007664 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007665 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7666 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007667 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007668 else
7669 {
7670 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007671 }
7672 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007673 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007674 {
7675 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007676 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007677 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007678 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007679 if(not $ParamTypeName) {
7680 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7681 }
7682 foreach my $Typedef (keys(%ChangedTypedef))
7683 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007684 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7685 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7686 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007687 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007688 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7689 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007690 if($ParamName eq "this"
7691 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007692 { # do NOT show first hidded "this"-parameter
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007693 next;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007694 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04007695 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007696 }
7697 else {
7698 push(@ParamArray, $ParamTypeName);
7699 }
7700 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007701 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7702 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007703 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007704 }
7705 else
7706 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007707 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007708 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007709 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007710 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007711 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007712 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7713 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007714 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007715 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007716 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7717 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007718 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007719 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007720 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7721 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007722 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007723 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007724 }
7725 }
7726 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007727 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007728 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007729 }
7730 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007731 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007732 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007733 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007734}
7735
7736sub create_member_decl($$)
7737{
7738 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007739 if($TName=~/\([\*]+\)/)
7740 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007741 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7742 return $TName;
7743 }
7744 else
7745 {
7746 my @ArraySizes = ();
7747 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7748 push(@ArraySizes, $1);
7749 }
7750 return $TName." ".$Member.join("", @ArraySizes);
7751 }
7752}
7753
7754sub getFuncType($)
7755{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007756 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7757 {
7758 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7759 {
7760 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7761 {
7762 if($Type eq "method_type") {
7763 return "Method";
7764 }
7765 elsif($Type eq "function_type") {
7766 return "Function";
7767 }
7768 else {
7769 return "Other";
7770 }
7771 }
7772 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007773 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007774 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007775}
7776
7777sub getFuncTypeId($)
7778{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007779 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7780 {
7781 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7782 return $1;
7783 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007784 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007785 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007786}
7787
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007788sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007789{ # "._N" or "$_N" in older GCC versions
7790 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007791}
7792
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007793sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007794{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007795 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7796 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007797 }
7798
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007799 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007800
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007801 if($_[1] ne "S")
7802 {
7803 $N=~s/\A[ ]+//g;
7804 $N=~s/[ ]+\Z//g;
7805 $N=~s/[ ]{2,}/ /g;
7806 }
7807
7808 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007809
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007810 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007811
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007812 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7813 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007814
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007815 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007816
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007817 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007818
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007819 if($_[1] eq "S")
7820 {
7821 if(index($N, "operator")!=-1) {
7822 $N=~s/\b(operator[ ]*)> >/$1>>/;
7823 }
7824 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007825
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007826 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007827}
7828
7829sub get_HeaderDeps($$)
7830{
7831 my ($AbsPath, $LibVersion) = @_;
7832 return () if(not $AbsPath or not $LibVersion);
7833 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7834 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7835 }
7836 my %IncDir = ();
7837 detect_recursive_includes($AbsPath, $LibVersion);
7838 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7839 {
7840 next if(not $HeaderPath);
7841 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7842 my $Dir = get_dirname($HeaderPath);
7843 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7844 {
7845 my $Dep = $Dir;
7846 if($Prefix)
7847 {
7848 if($OSgroup eq "windows")
7849 { # case insensitive seach on windows
7850 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7851 next;
7852 }
7853 }
7854 elsif($OSgroup eq "macos")
7855 { # seach in frameworks
7856 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7857 {
7858 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7859 {# frameworks
7860 my ($HFramework, $HName) = ($1, $2);
7861 $Dep = $HFramework;
7862 }
7863 else
7864 {# mismatch
7865 next;
7866 }
7867 }
7868 }
7869 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7870 { # Linux, FreeBSD
7871 next;
7872 }
7873 }
7874 if(not $Dep)
7875 { # nothing to include
7876 next;
7877 }
7878 if(is_default_include_dir($Dep))
7879 { # included by the compiler
7880 next;
7881 }
7882 if(get_depth($Dep)==1)
7883 { # too short
7884 next;
7885 }
7886 if(isLibcDir($Dep))
7887 { # do NOT include /usr/include/{sys,bits}
7888 next;
7889 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007890 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007891 }
7892 }
7893 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7894 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7895}
7896
7897sub sortIncPaths($$)
7898{
7899 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007900 if(not $ArrRef or $#{$ArrRef}<0) {
7901 return $ArrRef;
7902 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007903 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7904 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007905 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007906 return $ArrRef;
7907}
7908
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007909sub sortDeps($$$)
7910{
7911 if($Header_Dependency{$_[2]}{$_[0]}
7912 and not $Header_Dependency{$_[2]}{$_[1]}) {
7913 return 1;
7914 }
7915 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7916 and $Header_Dependency{$_[2]}{$_[1]}) {
7917 return -1;
7918 }
7919 return 0;
7920}
7921
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007922sub join_P($$)
7923{
7924 my $S = "/";
7925 if($OSgroup eq "windows") {
7926 $S = "\\";
7927 }
7928 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007929}
7930
7931sub get_namespace_additions($)
7932{
7933 my $NameSpaces = $_[0];
7934 my ($Additions, $AddNameSpaceId) = ("", 1);
7935 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7936 {
7937 next if($SkipNameSpaces{$Version}{$NS});
7938 next if(not $NS or $NameSpaces->{$NS}==-1);
7939 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7940 next if($NS=~/\A__/i);
7941 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007942 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007943 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7944 my @NS_Parts = split(/::/, $NS);
7945 next if($#NS_Parts==-1);
7946 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7947 foreach my $NS_Part (@NS_Parts)
7948 {
7949 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7950 $TypeDecl_Suffix .= "}";
7951 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007952 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007953 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7954 $Additions.=" $TypeDecl\n $FuncDecl\n";
7955 $AddNameSpaceId+=1;
7956 }
7957 return $Additions;
7958}
7959
7960sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007961{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007962 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007963 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007964 if($Fmt eq "windows")
7965 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007966 $Path=~s/\//\\/g;
7967 $Path=lc($Path);
7968 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007969 else
7970 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007971 $Path=~s/\\/\//g;
7972 }
7973 return $Path;
7974}
7975
7976sub inc_opt($$)
7977{
7978 my ($Path, $Style) = @_;
7979 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007980 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007981 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007982 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007983 return "-I\"".path_format($Path, "unix")."\"";
7984 }
7985 elsif($OSgroup eq "macos"
7986 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007987 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007988 return "-F".esc(get_dirname($Path));
7989 }
7990 else {
7991 return "-I".esc($Path);
7992 }
7993 }
7994 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007995 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007996 }
7997 return "";
7998}
7999
8000sub platformSpecs($)
8001{
8002 my $LibVersion = $_[0];
8003 my $Arch = getArch($LibVersion);
8004 if($OStarget eq "symbian")
8005 { # options for GCCE compiler
8006 my %Symbian_Opts = map {$_=>1} (
8007 "-D__GCCE__",
8008 "-DUNICODE",
8009 "-fexceptions",
8010 "-D__SYMBIAN32__",
8011 "-D__MARM_INTERWORK__",
8012 "-D_UNICODE",
8013 "-D__S60_50__",
8014 "-D__S60_3X__",
8015 "-D__SERIES60_3X__",
8016 "-D__EPOC32__",
8017 "-D__MARM__",
8018 "-D__EABI__",
8019 "-D__MARM_ARMV5__",
8020 "-D__SUPPORT_CPP_EXCEPTIONS__",
8021 "-march=armv5t",
8022 "-mapcs",
8023 "-mthumb-interwork",
8024 "-DEKA2",
8025 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
8026 );
8027 return join(" ", keys(%Symbian_Opts));
8028 }
8029 elsif($OSgroup eq "windows"
8030 and get_dumpmachine($GCC_PATH)=~/mingw/i)
8031 { # add options to MinGW compiler
8032 # to simulate the MSVC compiler
8033 my %MinGW_Opts = map {$_=>1} (
8034 "-D_WIN32",
8035 "-D_STDCALL_SUPPORTED",
8036 "-D__int64=\"long long\"",
8037 "-D__int32=int",
8038 "-D__int16=short",
8039 "-D__int8=char",
8040 "-D__possibly_notnullterminated=\" \"",
8041 "-D__nullterminated=\" \"",
8042 "-D__nullnullterminated=\" \"",
8043 "-D__w64=\" \"",
8044 "-D__ptr32=\" \"",
8045 "-D__ptr64=\" \"",
8046 "-D__forceinline=inline",
8047 "-D__inline=inline",
8048 "-D__uuidof(x)=IID()",
8049 "-D__try=",
8050 "-D__except(x)=",
8051 "-D__declspec(x)=__attribute__((x))",
8052 "-D__pragma(x)=",
8053 "-D_inline=inline",
8054 "-D__forceinline=__inline",
8055 "-D__stdcall=__attribute__((__stdcall__))",
8056 "-D__cdecl=__attribute__((__cdecl__))",
8057 "-D__fastcall=__attribute__((__fastcall__))",
8058 "-D__thiscall=__attribute__((__thiscall__))",
8059 "-D_stdcall=__attribute__((__stdcall__))",
8060 "-D_cdecl=__attribute__((__cdecl__))",
8061 "-D_fastcall=__attribute__((__fastcall__))",
8062 "-D_thiscall=__attribute__((__thiscall__))",
8063 "-DSHSTDAPI_(x)=x",
8064 "-D_MSC_EXTENSIONS",
8065 "-DSECURITY_WIN32",
8066 "-D_MSC_VER=1500",
8067 "-D_USE_DECLSPECS_FOR_SAL",
8068 "-D__noop=\" \"",
8069 "-DDECLSPEC_DEPRECATED=\" \"",
8070 "-D__builtin_alignof(x)=__alignof__(x)",
8071 "-DSORTPP_PASS");
8072 if($Arch eq "x86") {
8073 $MinGW_Opts{"-D_M_IX86=300"}=1;
8074 }
8075 elsif($Arch eq "x86_64") {
8076 $MinGW_Opts{"-D_M_AMD64=300"}=1;
8077 }
8078 elsif($Arch eq "ia64") {
8079 $MinGW_Opts{"-D_M_IA64=300"}=1;
8080 }
8081 return join(" ", keys(%MinGW_Opts));
8082 }
8083 return "";
8084}
8085
8086my %C_Structure = map {$_=>1} (
8087# FIXME: Can't separate union and struct data types before dumping,
8088# so it sometimes cause compilation errors for unknown reason
8089# when trying to declare TYPE* tmp_add_class_N
8090# This is a list of such structures + list of other C structures
8091 "sigval",
8092 "sigevent",
8093 "sigaction",
8094 "sigvec",
8095 "sigstack",
8096 "timeval",
8097 "timezone",
8098 "rusage",
8099 "rlimit",
8100 "wait",
8101 "flock",
8102 "stat",
8103 "_stat",
8104 "stat32",
8105 "_stat32",
8106 "stat64",
8107 "_stat64",
8108 "_stati64",
8109 "if_nameindex",
8110 "usb_device",
8111 "sigaltstack",
8112 "sysinfo",
8113 "timeLocale",
8114 "tcp_debug",
8115 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008116 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008117 "timespec",
8118 "random_data",
8119 "drand48_data",
8120 "_IO_marker",
8121 "_IO_FILE",
8122 "lconv",
8123 "sched_param",
8124 "tm",
8125 "itimerspec",
8126 "_pthread_cleanup_buffer",
8127 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008128 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008129 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008130 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008131 "sigcontext",
8132 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008133 # Mac
8134 "_timex",
8135 "_class_t",
8136 "_category_t",
8137 "_class_ro_t",
8138 "_protocol_t",
8139 "_message_ref_t",
8140 "_super_message_ref_t",
8141 "_ivar_t",
8142 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008143);
8144
8145sub getCompileCmd($$$)
8146{
8147 my ($Path, $Opt, $Inc) = @_;
8148 my $GccCall = $GCC_PATH;
8149 if($Opt) {
8150 $GccCall .= " ".$Opt;
8151 }
8152 $GccCall .= " -x ";
8153 if($OSgroup eq "macos") {
8154 $GccCall .= "objective-";
8155 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04008156
8157 if($EMERGENCY_MODE_48)
8158 { # workaround for GCC 4.8 (C only)
8159 $GccCall .= "c++";
8160 }
8161 elsif(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008162 { # compile as "C++" header
8163 # to obtain complete dump using GCC 4.0
8164 $GccCall .= "c++-header";
8165 }
8166 else
8167 { # compile as "C++" source
8168 # GCC 3.3 cannot compile headers
8169 $GccCall .= "c++";
8170 }
8171 if(my $Opts = platformSpecs($Version))
8172 {# platform-specific options
8173 $GccCall .= " ".$Opts;
8174 }
8175 # allow extra qualifications
8176 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008177 $GccCall .= " -fpermissive";
8178 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008179 if($NoStdInc)
8180 {
8181 $GccCall .= " -nostdinc";
8182 $GccCall .= " -nostdinc++";
8183 }
8184 if($CompilerOptions{$Version})
8185 { # user-defined options
8186 $GccCall .= " ".$CompilerOptions{$Version};
8187 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008188 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008189 if($Inc)
8190 { # include paths
8191 $GccCall .= " ".$Inc;
8192 }
8193 return $GccCall;
8194}
8195
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008196sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008197{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008198 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008199 my %HeaderElems = (
8200 # Types
8201 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008202 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008203 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8204 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008205 "time.h" => ["time_t"],
8206 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008207 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8208 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008209 "stdbool.h" => ["_Bool"],
8210 "rpc/xdr.h" => ["bool_t"],
8211 "in_systm.h" => ["n_long", "n_short"],
8212 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008213 "arpa/inet.h" => ["fw_src", "ip_src"],
8214 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008215 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008216 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008217 );
8218 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008219 foreach (keys(%HeaderElems))
8220 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008221 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008222 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008223 }
8224 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008225 my %Types = ();
8226 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8227 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008228 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008229 }
8230 if(keys(%Types))
8231 {
8232 my %AddHeaders = ();
8233 foreach my $Type (keys(%Types))
8234 {
8235 if(my $Header = $AutoPreamble{$Type})
8236 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008237 if(my $Path = identifyHeader($Header, $LibVersion))
8238 {
8239 if(skipHeader($Path, $LibVersion)) {
8240 next;
8241 }
8242 $Path = path_format($Path, $OSgroup);
8243 $AddHeaders{$Path}{"Type"} = $Type;
8244 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008245 }
8246 }
8247 }
8248 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008249 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008250 }
8251 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008252 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008253}
8254
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008255sub checkCTags($)
8256{
8257 my $Path = $_[0];
8258 if(not $Path) {
8259 return;
8260 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008261 my $CTags = undef;
8262
8263 if($OSgroup eq "bsd")
8264 { # use ectags on BSD
8265 $CTags = get_CmdPath("ectags");
8266 if(not $CTags) {
8267 printMsg("WARNING", "can't find \'ectags\' program");
8268 }
8269 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008270 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008271 $CTags = get_CmdPath("ctags");
8272 }
8273 if(not $CTags)
8274 {
8275 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008276 return;
8277 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008278
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008279 if($OSgroup ne "linux")
8280 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008281 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8282 if($Info!~/exuberant/i)
8283 {
8284 printMsg("WARNING", "incompatible version of \'ctags\' program");
8285 return;
8286 }
8287 }
8288
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008289 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008290 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008291 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008292 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008293 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008294 open(CTAGS, "<", $Out);
8295 while(my $Line = <CTAGS>)
8296 {
8297 chomp($Line);
8298 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008299 if(defined $Intrinsic_Keywords{$Name})
8300 { # noise
8301 next;
8302 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008303 if($Type eq "n")
8304 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008305 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008306 next;
8307 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008308 if(index($Scpe, "struct:")==0) {
8309 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008310 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008311 if(index($Scpe, "namespace:")==0)
8312 {
8313 if($Scpe=~s/\Anamespace://) {
8314 $Name = $Scpe."::".$Name;
8315 }
8316 }
8317 $TUnit_NameSpaces{$Version}{$Name} = 1;
8318 }
8319 elsif($Type eq "p")
8320 {
8321 if(not $Scpe or index($Scpe, "namespace:")==0) {
8322 $TUnit_Funcs{$Version}{$Name} = 1;
8323 }
8324 }
8325 elsif($Type eq "x")
8326 {
8327 if(not $Scpe or index($Scpe, "namespace:")==0) {
8328 $TUnit_Vars{$Version}{$Name} = 1;
8329 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008330 }
8331 }
8332 close(CTAGS);
8333}
8334
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008335sub preChange($$)
8336{
8337 my ($HeaderPath, $IncStr) = @_;
8338
8339 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8340 my $Content = undef;
8341
8342 if($OStarget eq "windows"
8343 and get_dumpmachine($GCC_PATH)=~/mingw/i
8344 and $MinGWMode{$Version}!=-1)
8345 { # modify headers to compile by MinGW
8346 if(not $Content)
8347 { # preprocessing
8348 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8349 }
8350 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8351 { # __asm { ... }
8352 $MinGWMode{$Version}=1;
8353 }
8354 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8355 { # comments after preprocessing
8356 $MinGWMode{$Version}=1;
8357 }
8358 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8359 { # 0xffui8
8360 $MinGWMode{$Version}=1;
8361 }
8362
8363 if($MinGWMode{$Version}) {
8364 printMsg("INFO", "Using MinGW compatibility mode");
8365 }
8366 }
8367
8368 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8369 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8370 { # rename C++ keywords in C code
8371 # disable this code by -cpp-compatible option
8372 if(not $Content)
8373 { # preprocessing
8374 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8375 }
8376 my $RegExp_C = join("|", keys(%CppKeywords_C));
8377 my $RegExp_F = join("|", keys(%CppKeywords_F));
8378 my $RegExp_O = join("|", keys(%CppKeywords_O));
8379
8380 my $Detected = undef;
8381
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008382 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 +04008383 { # MATCH:
8384 # int foo(int new, int class, int (*new)(int));
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008385 # int foo(char template[], char*);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008386 # unsigned private: 8;
8387 # DO NOT MATCH:
8388 # #pragma GCC visibility push(default)
8389 $CppMode{$Version} = 1;
8390 $Detected = "$1$2$3$4" if(not defined $Detected);
8391 }
8392 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8393 { # MATCH:
8394 # int delete(...);
8395 # int explicit(...);
8396 # DO NOT MATCH:
8397 # void operator delete(...)
8398 $CppMode{$Version} = 1;
8399 $Detected = "$1$2$3" if(not defined $Detected);
8400 }
8401 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8402 { # MATCH:
8403 # int bool;
8404 # DO NOT MATCH:
8405 # bool X;
8406 # return *this;
8407 # throw;
8408 $CppMode{$Version} = 1;
8409 $Detected = "$1$2$3" if(not defined $Detected);
8410 }
8411 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8412 { # MATCH:
8413 # int operator(...);
8414 # DO NOT MATCH:
8415 # int operator()(...);
8416 $CppMode{$Version} = 1;
8417 $Detected = "$1$2$3" if(not defined $Detected);
8418 }
8419 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8420 { # MATCH:
8421 # int foo(int operator);
8422 # int foo(int operator, int other);
8423 # DO NOT MATCH:
8424 # int operator,(...);
8425 $CppMode{$Version} = 1;
8426 $Detected = "$1$2$3" if(not defined $Detected);
8427 }
8428 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8429 { # MATCH:
8430 # int foo(gboolean *bool);
8431 # DO NOT MATCH:
8432 # void setTabEnabled(int index, bool);
8433 $CppMode{$Version} = 1;
8434 $Detected = "$1$2$3" if(not defined $Detected);
8435 }
8436 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8437 { # MATCH:
8438 # int foo(int* this);
8439 # int bar(int this);
8440 # int baz(int throw);
8441 # DO NOT MATCH:
8442 # foo(X, this);
8443 $CppMode{$Version} = 1;
8444 $Detected = "$1$2$3$4" if(not defined $Detected);
8445 }
8446 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8447 { # MATCH:
8448 # struct template {...};
8449 # extern template foo(...);
8450 $CppMode{$Version} = 1;
8451 $Detected = "$1$2" if(not defined $Detected);
8452 }
8453
8454 if($CppMode{$Version} == 1)
8455 {
8456 if($Debug)
8457 {
8458 $Detected=~s/\A\s+//g;
8459 printMsg("INFO", "Detected code: \"$Detected\"");
8460 }
8461 }
8462
8463 # remove typedef enum NAME NAME;
8464 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8465 my $N = 0;
8466 while($N<=$#FwdTypedefs-1)
8467 {
8468 my $S = $FwdTypedefs[$N];
8469 if($S eq $FwdTypedefs[$N+1])
8470 {
8471 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008472 $CppMode{$Version} = 1;
8473
8474 if($Debug) {
8475 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8476 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008477 }
8478 $N+=2;
8479 }
8480
8481 if($CppMode{$Version}==1) {
8482 printMsg("INFO", "Using C++ compatibility mode");
8483 }
8484 }
8485
8486 if($CppMode{$Version}==1
8487 or $MinGWMode{$Version}==1)
8488 {
8489 my $IPath = $TMP_DIR."/dump$Version.i";
8490 writeFile($IPath, $Content);
8491 return $IPath;
8492 }
8493
8494 return undef;
8495}
8496
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008497sub getDump()
8498{
8499 if(not $GCC_PATH) {
8500 exitStatus("Error", "internal error - GCC path is not set");
8501 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008502
8503 my @Headers = keys(%{$Registered_Headers{$Version}});
8504 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8505
8506 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8507
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008508 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008509 my $HeaderPath = $TmpHeaderPath;
8510
8511 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008512 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008513 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8514 {
8515 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008516 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008517 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008518 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008519 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8520 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008521 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008522 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008523 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008524 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8525 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8526 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008527 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008528 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008529
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008530 if($ExtraInfo)
8531 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008532 if($IncludeString) {
8533 writeFile($ExtraInfo."/include-string", $IncludeString);
8534 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008535 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8536 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008537
8538 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8539 {
8540 my $REDIR = "";
8541 foreach my $P1 (sort @Redirects) {
8542 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8543 }
8544 writeFile($ExtraInfo."/include-redirect", $REDIR);
8545 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008546 }
8547
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008548 if(not keys(%{$TargetHeaders{$Version}}))
8549 { # Target headers
8550 addTargetHeaders($Version);
8551 }
8552
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008553 # clean memory
8554 %RecursiveIncludes = ();
8555 %Header_Include_Prefix = ();
8556 %Header_Includes = ();
8557
8558 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008559 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008560 delete($Cache{"detect_header_includes"});
8561 delete($Cache{"selectSystemHeader"});
8562
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008563 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008564 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8565 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008566
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008567 if($ExtraInfo)
8568 { # extra information for other tools
8569 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8570 }
8571
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008572 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008573 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008574 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008575
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008576 if($COMMON_LANGUAGE{$Version} eq "C++") {
8577 checkCTags($Pre);
8578 }
8579
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008580 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8581 { # try to correct the preprocessor output
8582 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008583 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008584
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008585 if($COMMON_LANGUAGE{$Version} eq "C++")
8586 { # add classes and namespaces to the dump
8587 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008588 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008589 or $MinGWMode{$Version}==1) {
8590 $CHdump .= " -fpreprocessed";
8591 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008592 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008593 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008594 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008595 chdir($ORIG_DIR);
8596 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8597 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008598 my $Content = readFile($ClassDump);
8599 foreach my $ClassInfo (split(/\n\n/, $Content))
8600 {
8601 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8602 {
8603 my $CName = $1;
8604 next if($CName=~/\A(__|_objc_|_opaque_)/);
8605 $TUnit_NameSpaces{$Version}{$CName} = -1;
8606 if($CName=~/\A[\w:]+\Z/)
8607 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008608 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008609 }
8610 if($CName=~/(\w[\w:]*)::/)
8611 { # namespaces
8612 my $NS = $1;
8613 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8614 $TUnit_NameSpaces{$Version}{$NS} = 1;
8615 }
8616 }
8617 }
8618 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8619 { # read v-tables (advanced approach)
8620 my ($CName, $VTable) = ($1, $2);
8621 $ClassVTable_Content{$Version}{$CName} = $VTable;
8622 }
8623 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008624 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8625 { # add user-defined namespaces
8626 $TUnit_NameSpaces{$Version}{$NS} = 1;
8627 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008628 if($Debug)
8629 { # debug mode
8630 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008631 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008632 }
8633 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008634 }
8635
8636 # add namespaces and classes
8637 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8638 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008639 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008640 }
8641 # some GCC versions don't include class methods to the TU dump by default
8642 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008643 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008644 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8645 {
8646 next if($C_Structure{$CName});
8647 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008648 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008649 if(not $Force and $GCC_44
8650 and $OSgroup eq "linux")
8651 { # optimization for linux with GCC >= 4.4
8652 # disable this code by -force option
8653 if(index($CName, "::")!=-1)
8654 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008655 next;
8656 }
8657 }
8658 else
8659 {
8660 if($CName=~/\A(.+)::[^:]+\Z/
8661 and $TUnit_Classes{$Version}{$1})
8662 { # classes inside other classes
8663 next;
8664 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008665 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008666 if(defined $TUnit_Funcs{$Version}{$CName})
8667 { # the same name for a function and type
8668 next;
8669 }
8670 if(defined $TUnit_Vars{$Version}{$CName})
8671 { # the same name for a variable and type
8672 next;
8673 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008674 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8675 }
8676 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008677 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008678 }
8679 }
8680 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8681 # create TU dump
8682 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +04008683 if($UserLang eq "C") {
8684 $TUdump .= " -U__cplusplus -D_Bool=\"bool\"";
8685 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008686 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008687 or $MinGWMode{$Version}==1) {
8688 $TUdump .= " -fpreprocessed";
8689 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008690 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008691 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8692 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008693 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008694 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008695 if($?)
8696 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008697 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008698 { # try to recompile
8699 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008700 if($CppMode{$Version}==1
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008701 and index($Errors, "c99_")!=-1
8702 and not defined $CppIncompat)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008703 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008704 $CppMode{$Version}=-1;
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +04008705
8706 if($Debug)
8707 {
8708 # printMsg("INFO", $Errors);
8709 }
8710
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008711 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008712 resetLogging($Version);
8713 $TMP_DIR = tempdir(CLEANUP=>1);
8714 return getDump();
8715 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008716 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008717 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008718 { # add auto preamble headers and try again
8719 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008720 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008721 foreach my $Num (0 .. $#Headers)
8722 {
8723 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008724 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8725 {
8726 push_U($Include_Preamble{$Version}, $Path);
8727 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008728 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008729 }
8730 resetLogging($Version);
8731 $TMP_DIR = tempdir(CLEANUP=>1);
8732 return getDump();
8733 }
8734 elsif($Cpp0xMode{$Version}!=-1
8735 and ($Errors=~/\Q-std=c++0x\E/
8736 or $Errors=~/is not a class or namespace/))
8737 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008738 if(check_gcc($GCC_PATH, "4.6"))
8739 {
8740 $Cpp0xMode{$Version}=-1;
8741 printMsg("INFO", "Enabling c++0x mode");
8742 resetLogging($Version);
8743 $TMP_DIR = tempdir(CLEANUP=>1);
8744 $CompilerOptions{$Version} .= " -std=c++0x";
8745 return getDump();
8746 }
8747 else {
8748 printMsg("WARNING", "Probably c++0x construction detected");
8749 }
8750
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008751 }
8752 elsif($MinGWMode{$Version}==1)
8753 { # disable MinGW mode and try again
8754 $MinGWMode{$Version}=-1;
8755 resetLogging($Version);
8756 $TMP_DIR = tempdir(CLEANUP=>1);
8757 return getDump();
8758 }
8759 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008760 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008761 else {
8762 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008763 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008764 printMsg("ERROR", "some errors occurred when compiling headers");
8765 printErrorLog($Version);
8766 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008767 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008768 }
8769 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008770 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008771 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008772
8773 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8774 return $TUs[0];
8775 }
8776 else
8777 {
8778 my $Msg = "can't compile header(s)";
8779 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8780 $Msg .= "\nDid you install G++?";
8781 }
8782 exitStatus("Cannot_Compile", $Msg);
8783 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008784}
8785
8786sub cmd_file($)
8787{
8788 my $Path = $_[0];
8789 return "" if(not $Path or not -e $Path);
8790 if(my $CmdPath = get_CmdPath("file")) {
8791 return `$CmdPath -b \"$Path\"`;
8792 }
8793 return "";
8794}
8795
8796sub getIncString($$)
8797{
8798 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008799 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008800 my $String = "";
8801 foreach (@{$ArrRef}) {
8802 $String .= " ".inc_opt($_, $Style);
8803 }
8804 return $String;
8805}
8806
8807sub getIncPaths(@)
8808{
8809 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008810 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008811 if($INC_PATH_AUTODETECT{$Version})
8812 { # auto-detecting dependencies
8813 my %Includes = ();
8814 foreach my $HPath (@HeaderPaths)
8815 {
8816 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8817 {
8818 if($Skip_Include_Paths{$Version}{$Dir}) {
8819 next;
8820 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008821 if($SystemRoot)
8822 {
8823 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8824 next;
8825 }
8826 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008827 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008828 }
8829 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008830 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008831 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008832 }
8833 }
8834 else
8835 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008836 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008837 }
8838 return \@IncPaths;
8839}
8840
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008841sub push_U($@)
8842{ # push unique
8843 if(my $Array = shift @_)
8844 {
8845 if(@_)
8846 {
8847 my %Exist = map {$_=>1} @{$Array};
8848 foreach my $Elem (@_)
8849 {
8850 if(not defined $Exist{$Elem})
8851 {
8852 push(@{$Array}, $Elem);
8853 $Exist{$Elem} = 1;
8854 }
8855 }
8856 }
8857 }
8858}
8859
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008860sub callPreprocessor($$$)
8861{
8862 my ($Path, $Inc, $LibVersion) = @_;
8863 return "" if(not $Path or not -f $Path);
8864 my $IncludeString=$Inc;
8865 if(not $Inc) {
8866 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8867 }
8868 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008869 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008870 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008871 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008872}
8873
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008874sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008875{ # native "find" is much faster than File::Find (~6x)
8876 # also the File::Find doesn't support --maxdepth N option
8877 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008878 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008879 return () if(not $Path or not -e $Path);
8880 if($OSgroup eq "windows")
8881 {
8882 my $DirCmd = get_CmdPath("dir");
8883 if(not $DirCmd) {
8884 exitStatus("Not_Found", "can't find \"dir\" command");
8885 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008886 $Path = get_abs_path($Path);
8887 $Path = path_format($Path, $OSgroup);
8888 my $Cmd = $DirCmd." \"$Path\" /B /O";
8889 if($MaxDepth!=1) {
8890 $Cmd .= " /S";
8891 }
8892 if($Type eq "d") {
8893 $Cmd .= " /AD";
8894 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008895 elsif($Type eq "f") {
8896 $Cmd .= " /A-D";
8897 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008898 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008899 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008900 {
8901 if(not $UseRegex)
8902 { # FIXME: how to search file names in MS shell?
8903 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008904 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008905 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008906 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008907 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008908 }
8909 my @AbsPaths = ();
8910 foreach my $File (@Files)
8911 {
8912 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008913 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008914 }
8915 if($Type eq "f" and not -f $File)
8916 { # skip dirs
8917 next;
8918 }
8919 push(@AbsPaths, path_format($File, $OSgroup));
8920 }
8921 if($Type eq "d") {
8922 push(@AbsPaths, $Path);
8923 }
8924 return @AbsPaths;
8925 }
8926 else
8927 {
8928 my $FindCmd = get_CmdPath("find");
8929 if(not $FindCmd) {
8930 exitStatus("Not_Found", "can't find a \"find\" command");
8931 }
8932 $Path = get_abs_path($Path);
8933 if(-d $Path and -l $Path
8934 and $Path!~/\/\Z/)
8935 { # for directories that are symlinks
8936 $Path.="/";
8937 }
8938 my $Cmd = $FindCmd." \"$Path\"";
8939 if($MaxDepth) {
8940 $Cmd .= " -maxdepth $MaxDepth";
8941 }
8942 if($Type) {
8943 $Cmd .= " -type $Type";
8944 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008945 if($Name and not $UseRegex)
8946 { # wildcards
8947 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008948 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008949 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008950 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008951 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8952 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008953 my @Files = split(/\n/, $Res);
8954 if($Name and $UseRegex)
8955 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008956 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008957 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008958 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008959 }
8960}
8961
8962sub unpackDump($)
8963{
8964 my $Path = $_[0];
8965 return "" if(not $Path or not -e $Path);
8966 $Path = get_abs_path($Path);
8967 $Path = path_format($Path, $OSgroup);
8968 my ($Dir, $FileName) = separate_path($Path);
8969 my $UnpackDir = $TMP_DIR."/unpack";
8970 rmtree($UnpackDir);
8971 mkpath($UnpackDir);
8972 if($FileName=~s/\Q.zip\E\Z//g)
8973 { # *.zip
8974 my $UnzipCmd = get_CmdPath("unzip");
8975 if(not $UnzipCmd) {
8976 exitStatus("Not_Found", "can't find \"unzip\" command");
8977 }
8978 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008979 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008980 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008981 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008982 }
8983 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008984 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008985 if(not @Contents) {
8986 exitStatus("Error", "can't extract \'$Path\'");
8987 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008988 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008989 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008990 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008991 { # *.tar.gz
8992 if($OSgroup eq "windows")
8993 { # -xvzf option is not implemented in tar.exe (2003)
8994 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8995 my $TarCmd = get_CmdPath("tar");
8996 if(not $TarCmd) {
8997 exitStatus("Not_Found", "can't find \"tar\" command");
8998 }
8999 my $GzipCmd = get_CmdPath("gzip");
9000 if(not $GzipCmd) {
9001 exitStatus("Not_Found", "can't find \"gzip\" command");
9002 }
9003 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04009004 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009005 if($?) {
9006 exitStatus("Error", "can't extract \'$Path\'");
9007 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009008 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009009 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009010 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009011 }
9012 chdir($ORIG_DIR);
9013 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009014 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009015 if(not @Contents) {
9016 exitStatus("Error", "can't extract \'$Path\'");
9017 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009018 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009019 }
9020 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009021 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009022 my $TarCmd = get_CmdPath("tar");
9023 if(not $TarCmd) {
9024 exitStatus("Not_Found", "can't find \"tar\" command");
9025 }
9026 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009027 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009028 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009029 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009030 }
9031 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009032 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009033 if(not @Contents) {
9034 exitStatus("Error", "can't extract \'$Path\'");
9035 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009036 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009037 }
9038 }
9039}
9040
9041sub createArchive($$)
9042{
9043 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009044 if(not $To) {
9045 $To = ".";
9046 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009047 if(not $Path or not -e $Path
9048 or not -d $To) {
9049 return "";
9050 }
9051 my ($From, $Name) = separate_path($Path);
9052 if($OSgroup eq "windows")
9053 { # *.zip
9054 my $ZipCmd = get_CmdPath("zip");
9055 if(not $ZipCmd) {
9056 exitStatus("Not_Found", "can't find \"zip\"");
9057 }
9058 my $Pkg = $To."/".$Name.".zip";
9059 unlink($Pkg);
9060 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04009061 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009062 if($?)
9063 { # cannot allocate memory (or other problems with "zip")
9064 unlink($Path);
9065 exitStatus("Error", "can't pack the ABI dump: ".$!);
9066 }
9067 chdir($ORIG_DIR);
9068 unlink($Path);
9069 return $Pkg;
9070 }
9071 else
9072 { # *.tar.gz
9073 my $TarCmd = get_CmdPath("tar");
9074 if(not $TarCmd) {
9075 exitStatus("Not_Found", "can't find \"tar\"");
9076 }
9077 my $GzipCmd = get_CmdPath("gzip");
9078 if(not $GzipCmd) {
9079 exitStatus("Not_Found", "can't find \"gzip\"");
9080 }
9081 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
9082 unlink($Pkg);
9083 chdir($From);
9084 system($TarCmd, "-czf", $Pkg, $Name);
9085 if($?)
9086 { # cannot allocate memory (or other problems with "tar")
9087 unlink($Path);
9088 exitStatus("Error", "can't pack the ABI dump: ".$!);
9089 }
9090 chdir($ORIG_DIR);
9091 unlink($Path);
9092 return $To."/".$Name.".tar.gz";
9093 }
9094}
9095
9096sub is_header_file($)
9097{
9098 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
9099 return $_[0];
9100 }
9101 return 0;
9102}
9103
9104sub is_not_header($)
9105{
9106 if($_[0]=~/\.\w+\Z/
9107 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
9108 return 1;
9109 }
9110 return 0;
9111}
9112
9113sub is_header($$$)
9114{
9115 my ($Header, $UserDefined, $LibVersion) = @_;
9116 return 0 if(-d $Header);
9117 if(-f $Header) {
9118 $Header = get_abs_path($Header);
9119 }
9120 else
9121 {
9122 if(is_abs($Header))
9123 { # incorrect absolute path
9124 return 0;
9125 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009126 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009127 $Header = $HPath;
9128 }
9129 else
9130 { # can't find header
9131 return 0;
9132 }
9133 }
9134 if($Header=~/\.\w+\Z/)
9135 { # have an extension
9136 return is_header_file($Header);
9137 }
9138 else
9139 {
9140 if($UserDefined==2)
9141 { # specified on the command line
9142 if(cmd_file($Header)!~/HTML|XML/i) {
9143 return $Header;
9144 }
9145 }
9146 elsif($UserDefined)
9147 { # specified in the XML-descriptor
9148 # header file without an extension
9149 return $Header;
9150 }
9151 else
9152 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04009153 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009154 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009155 { # !~/HTML|XML|shared|dynamic/i
9156 return $Header;
9157 }
9158 }
9159 }
9160 return 0;
9161}
9162
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009163sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009164{
9165 my $LibVersion = $_[0];
9166 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9167 {
9168 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009169 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009170
9171 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9172 detect_recursive_includes($RegHeader, $LibVersion);
9173 }
9174
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009175 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9176 {
9177 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009178
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009179 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009180 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9181 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009182 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009183 }
9184 }
9185 }
9186}
9187
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009188sub familiarDirs($$)
9189{
9190 my ($D1, $D2) = @_;
9191 if($D1 eq $D2) {
9192 return 1;
9193 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009194
9195 my $U1 = index($D1, "/usr/");
9196 my $U2 = index($D2, "/usr/");
9197
9198 if($U1==0 and $U2!=0) {
9199 return 0;
9200 }
9201
9202 if($U2==0 and $U1!=0) {
9203 return 0;
9204 }
9205
9206 if(index($D2, $D1."/")==0) {
9207 return 1;
9208 }
9209
9210 # /usr/include/DIR
9211 # /home/user/DIR
9212
9213 my $DL = get_depth($D1);
9214
9215 my @Dirs1 = ($D1);
9216 while($DL - get_depth($D1)<=2
9217 and get_depth($D1)>=4
9218 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9219 push(@Dirs1, $D1);
9220 }
9221
9222 my @Dirs2 = ($D2);
9223 while(get_depth($D2)>=4
9224 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9225 push(@Dirs2, $D2);
9226 }
9227
9228 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009229 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009230 foreach my $P2 (@Dirs2)
9231 {
9232
9233 if($P1 eq $P2) {
9234 return 1;
9235 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009236 }
9237 }
9238 return 0;
9239}
9240
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009241sub readHeaders($)
9242{
9243 $Version = $_[0];
9244 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9245 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009246 if($Debug)
9247 { # debug mode
9248 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009249 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009250 }
9251 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009252}
9253
9254sub prepareTypes($)
9255{
9256 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009257 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009258 { # support for old ABI dumps
9259 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009260 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009261 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009262 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9263 if($TName=~/\A(\w+)::(\w+)/) {
9264 my ($P1, $P2) = ($1, $2);
9265 if($P1 eq $P2) {
9266 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009267 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009268 else {
9269 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9270 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009271 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009272 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009273 }
9274 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009275 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009276 { # support for old ABI dumps
9277 # V < 2.5: array size == "number of elements"
9278 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009279 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009280 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009281 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009282 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009283 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009284 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009285 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009286 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009287 $Size *= $Base{"Size"};
9288 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009289 }
9290 else
9291 { # array[] is a pointer
9292 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009293 }
9294 }
9295 }
9296 }
9297 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009298 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009299 { # support for old ABI dumps
9300 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009301 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009302 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009303 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009304 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009305 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009306 my %Type = get_Type($TypeId, $LibVersion);
9307 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9308 my %Type2 = get_Type($TypeId_2, $V2);
9309 if($Type{"Size"} ne $Type2{"Size"}) {
9310 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009311 }
9312 }
9313 }
9314 }
9315}
9316
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009317sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009318{
9319 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009320
9321 if(not keys(%{$SymbolInfo{$LibVersion}}))
9322 { # check if input is valid
9323 if(not $ExtendedCheck and not $CheckObjectsOnly)
9324 {
9325 if($CheckHeadersOnly) {
9326 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9327 }
9328 else {
9329 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9330 }
9331 }
9332 }
9333
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009334 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009335 if(not checkDump(1, "2.10")
9336 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009337 { # different formats
9338 $Remangle = 1;
9339 }
9340 if($CheckHeadersOnly)
9341 { # different languages
9342 if($UserLang)
9343 { # --lang=LANG for both versions
9344 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9345 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9346 {
9347 if($UserLang eq "C++")
9348 { # remangle symbols
9349 $Remangle = 1;
9350 }
9351 elsif($UserLang eq "C")
9352 { # remove mangling
9353 $Remangle = -1;
9354 }
9355 }
9356 }
9357 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009358
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009359 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009360 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009361 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009362 { # support for old ABI dumps
9363 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9364 {
9365 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9366 {
9367 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9368 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009369 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009370 if(defined $DVal and $DVal ne "")
9371 {
9372 if($TName eq "char") {
9373 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9374 }
9375 elsif($TName eq "bool") {
9376 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9377 }
9378 }
9379 }
9380 }
9381 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009382 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009383 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009384 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9385 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009386 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009387 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9388 # + support for old ABI dumps
9389 next;
9390 }
9391 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009392 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009393 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009394 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009395 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009396
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009397 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009398 if(not checkDump(1, "2.12")
9399 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009400 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009401 if($ShortName eq "operator>>")
9402 {
9403 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9404 { # corrected mangling of operator>>
9405 $SRemangle = 1;
9406 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009407 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009408 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9409 {
9410 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9411 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9412 { # corrected mangling of const global data
9413 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9414 # and incorrectly mangled by old ACC versions
9415 $SRemangle = 1;
9416 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009417 }
9418 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009419 if(not $CheckHeadersOnly)
9420 { # support for old ABI dumps
9421 if(not checkDump(1, "2.17")
9422 or not checkDump(2, "2.17"))
9423 {
9424 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9425 {
9426 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9427 {
9428 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9429 {
9430 $MnglName = $ShortName;
9431 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9432 }
9433 }
9434 }
9435 }
9436 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009437 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009438 { # support for old ABI dumps: some symbols are not mangled in old dumps
9439 # mangle both sets of symbols (old and new)
9440 # NOTE: remangling all symbols by the same mangler
9441 if($MnglName=~/\A_ZN(V|)K/)
9442 { # mangling may be incorrect on old ABI dumps
9443 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009444 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009445 }
9446 if($MnglName=~/\A_ZN(K|)V/)
9447 { # mangling may be incorrect on old ABI dumps
9448 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009449 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009450 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009451 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9452 or (not $ClassID and $CheckHeadersOnly)
9453 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9454 { # support for old ABI dumps, GCC >= 4.0
9455 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009456 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009457 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009458 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009459 $MangledNames{$LibVersion}{$MnglName} = 1;
9460 }
9461 }
9462 }
9463 elsif($Remangle==-1)
9464 { # remove mangling
9465 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009466 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009467 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009468 if(not $MnglName) {
9469 next;
9470 }
9471 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9472 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009473 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9474
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009475 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009476 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009477 { # support for old dumps
9478 # add "Volatile" attribute
9479 if($MnglName=~/_Z(K|)V/) {
9480 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9481 }
9482 }
9483 # symbol and its symlink have same signatures
9484 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009485 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009486 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009487
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009488 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9489 {
9490 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9491 if($SymVer{$LibVersion}{$Alias}) {
9492 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9493 }
9494 }
9495
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009496 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009497 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009498 }
9499 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9500 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9501 }
9502 if($ExtendedCheck)
9503 { # --ext option
9504 addExtension($LibVersion);
9505 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009506
9507 # clean memory
9508 delete($SymbolInfo{$LibVersion});
9509
9510 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009511 { # detect allocable classes with public exported constructors
9512 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009513 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009514 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009515 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009516 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009517 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9518 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009519 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009520 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009521 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009522 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009523 $AllocableClass{$LibVersion}{$ClassName} = 1;
9524 }
9525 }
9526 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009527 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009528 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009529 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009530 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009531 if($CheckHeadersOnly)
9532 {
9533 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9534 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9535 { # all symbols except non-virtual inline
9536 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9537 }
9538 }
9539 else {
9540 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009541 }
9542 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009543 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009544 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009545 }
9546 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009547 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009548 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009549 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009550 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009551 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009552 if(defined $Base{"Type"}
9553 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009554 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009555 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009556 if($Name=~/<([^<>\s]+)>/)
9557 {
9558 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9559 $ReturnedClass{$LibVersion}{$Tid} = 1;
9560 }
9561 }
9562 else {
9563 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9564 }
9565 }
9566 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009567 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009568 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009569 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009570 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009571 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009572 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009573 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009574 if($Base{"Type"}=~/Struct|Class/)
9575 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009576 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009577 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9578 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009579 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009580 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009581 }
9582 }
9583 }
9584 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009585
9586 # mapping {short name => symbols}
9587 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009588 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009589 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009590 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009591 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009592 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009593 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009594 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009595 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9596 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009597 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009598 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009599 }
9600 }
9601 }
9602 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009603
9604 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009605 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009606 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009607 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009608 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009609 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9610 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009611 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009612 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009613 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009614 $ClassNames{$LibVersion}{$TName} = 1;
9615 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009616 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009617 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9618 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009619 }
9620 }
9621 }
9622 }
9623 }
9624}
9625
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009626sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009627{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009628 my ($Tid, $LibVersion) = @_;
9629 if(not $Tid) {
9630 return $Tid;
9631 }
9632
9633 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9634 {
9635 if($TName_Tid{$LibVersion}{$Name}) {
9636 return $TName_Tid{$LibVersion}{$Name};
9637 }
9638 }
9639
9640 return $Tid;
9641}
9642
9643sub register_SymbolUsage($$$)
9644{
9645 my ($InfoId, $UsedType, $LibVersion) = @_;
9646
9647 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9648 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9649 {
9650 register_TypeUsage($RTid, $UsedType, $LibVersion);
9651 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9652 }
9653 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9654 {
9655 register_TypeUsage($FCid, $UsedType, $LibVersion);
9656 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9657
9658 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9659 { # register "this" pointer
9660 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9661 }
9662 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9663 { # register "this" pointer (const method)
9664 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9665 }
9666 }
9667 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9668 {
9669 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9670 {
9671 register_TypeUsage($PTid, $UsedType, $LibVersion);
9672 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9673 }
9674 }
9675 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9676 {
9677 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9678 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9679 register_TypeUsage($TTid, $UsedType, $LibVersion);
9680 }
9681 }
9682}
9683
9684sub register_TypeUsage($$$)
9685{
9686 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009687 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009688 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009689 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009690 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009691 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009692 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009693 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009694
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009695 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009696 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009697 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009698 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009699 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009700 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9701 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9702 }
9703 }
9704
9705 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9706 {
9707 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009708 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009709 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009710 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9711 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009712 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009713 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9714 {
9715 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9716 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009717 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009718 }
9719 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009720 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009721 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009722 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009723 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9724 {
9725 register_TypeUsage($MTid, $UsedType, $LibVersion);
9726 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009727 }
9728 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009729 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009730 or $TInfo{"Type"} eq "MethodPtr"
9731 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009732 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009733 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009734 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009735 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009736 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009737 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009738 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9739 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009740 }
9741 }
9742 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009743 if($TInfo{"Type"} eq "FieldPtr")
9744 {
9745 if(my $RTid = $TInfo{"Return"}) {
9746 register_TypeUsage($RTid, $UsedType, $LibVersion);
9747 }
9748 if(my $CTid = $TInfo{"Class"}) {
9749 register_TypeUsage($CTid, $UsedType, $LibVersion);
9750 }
9751 }
9752 if($TInfo{"Type"} eq "MethodPtr")
9753 {
9754 if(my $CTid = $TInfo{"Class"}) {
9755 register_TypeUsage($CTid, $UsedType, $LibVersion);
9756 }
9757 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009758 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009759 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009760 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009761 $UsedType->{$TypeId} = 1;
9762 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9763 {
9764 register_TypeUsage($BTid, $UsedType, $LibVersion);
9765 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9766 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009767 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009768 else
9769 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9770 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009771 }
9772 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009773}
9774
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009775sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009776{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009777 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9778
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009779 if($Level eq "Dump")
9780 {
9781 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9782 { # TODO: check if this symbol is from
9783 # base classes of other target symbols
9784 return 1;
9785 }
9786 }
9787
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009788 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9789 { # stdc++ interfaces
9790 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009791 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009792
9793 my $Target = 0;
9794 if(my $Header = $SInfo->{"Header"}) {
9795 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9796 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009797 if($ExtendedCheck)
9798 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009799 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009800 $Target = 1;
9801 }
9802 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009803 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009804 {
9805 if($Target)
9806 {
9807 if($Level eq "Dump")
9808 { # dumped
9809 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009810 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009811 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009812 return 1;
9813 }
9814 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009815 else {
9816 return 1;
9817 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009818 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009819 elsif($Level eq "Source")
9820 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009821 return 1;
9822 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009823 elsif($Level eq "Binary")
9824 { # checked
9825 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9826 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9827 return 1;
9828 }
9829 }
9830 }
9831 }
9832 else
9833 { # library is available
9834 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9835 { # exported symbols
9836 return 1;
9837 }
9838 if($Level eq "Dump")
9839 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009840 if($BinaryOnly)
9841 {
9842 if($SInfo->{"Data"})
9843 {
9844 if($Target) {
9845 return 1;
9846 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009847 }
9848 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009849 else
9850 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009851 if($Target) {
9852 return 1;
9853 }
9854 }
9855 }
9856 elsif($Level eq "Source")
9857 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009858 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
9859 or isInLineInst($Symbol, $SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009860 { # skip LOCAL symbols
9861 if($Target) {
9862 return 1;
9863 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009864 }
9865 }
9866 elsif($Level eq "Binary")
9867 { # checked
9868 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9869 {
9870 if($Target) {
9871 return 1;
9872 }
9873 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009874 }
9875 }
9876 return 0;
9877}
9878
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009879sub cleanDump($)
9880{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009881 my $LibVersion = $_[0];
9882 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9883 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009884 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9885 {
9886 delete($SymbolInfo{$LibVersion}{$InfoId});
9887 next;
9888 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009889 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009890 if(not $MnglName)
9891 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009892 delete($SymbolInfo{$LibVersion}{$InfoId});
9893 next;
9894 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009895 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009896 if(not $ShortName)
9897 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009898 delete($SymbolInfo{$LibVersion}{$InfoId});
9899 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009900 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009901 if($MnglName eq $ShortName)
9902 { # remove duplicate data
9903 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009904 }
9905 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9906 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9907 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009908 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9909 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9910 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +04009911 delete($SymbolInfo{$LibVersion}{$InfoId}{"Type"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009912 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009913 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009914 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009915 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9916 {
9917 delete($TypeInfo{$LibVersion}{$Tid});
9918 next;
9919 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009920 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009921 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009922 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009923 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9924 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9925 }
9926 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009927 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9928 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9929 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009930 }
9931}
9932
9933sub selectType($$)
9934{
9935 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009936
9937 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9938 {
9939 if(defined $TypeInfo{$LibVersion}{$Dupl})
9940 {
9941 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9942 { # duplicate
9943 return 0;
9944 }
9945 }
9946 }
9947
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009948 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9949 {
9950 if(not isBuiltIn($THeader))
9951 {
9952 if($TypeInfo{$LibVersion}{$Tid}{"Type"}=~/Class|Struct|Union|Enum|Typedef/)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009953 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009954 if(not isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"}))
9955 {
9956 if(is_target_header($THeader, $LibVersion))
9957 { # from target headers
9958 if(not selfTypedef($Tid, $LibVersion)) {
9959 return 1;
9960 }
9961 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009962 }
9963 }
9964 }
9965 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009966 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009967}
9968
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009969sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009970{ # remove unused data types from the ABI dump
9971 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009972
9973 my %UsedType = ();
9974
9975 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009976 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009977 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009978 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009979 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009980 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009981 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009982 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009983 next;
9984 }
9985
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009986 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009987 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009988 if(selectType($Tid, $LibVersion))
9989 {
9990 my %Tree = ();
9991 register_TypeUsage($Tid, \%Tree, $LibVersion);
9992
9993 my $Tmpl = 0;
9994 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9995 {
9996 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9997 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9998 {
9999 $Tmpl = 1;
10000 last;
10001 }
10002 }
10003 if(not $Tmpl)
10004 {
10005 foreach (keys(%Tree)) {
10006 $UsedType{$_} = 1;
10007 }
10008 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010009 }
10010 }
10011 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010012
10013 my %Delete = ();
10014
10015 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010016 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010017 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010018 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010019 next;
10020 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010021
10022 if($Kind eq "Extra")
10023 {
10024 my %Tree = ();
10025 register_TypeUsage($Tid, \%Tree, $LibVersion);
10026
10027 foreach (sort {int($a)<=>int($b)} keys(%Tree))
10028 {
10029 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
10030 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
10031 {
10032 $Delete{$Tid} = 1;
10033 last;
10034 }
10035 }
10036 }
10037 else
10038 {
10039 # remove type
10040 delete($TypeInfo{$LibVersion}{$Tid});
10041 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010042 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010043
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040010044 if($Kind eq "Extra")
10045 { # remove duplicates
10046 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
10047 {
10048 if($UsedType{$Tid})
10049 { # All & Extended
10050 next;
10051 }
10052
10053 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10054
10055 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
10056 delete($TypeInfo{$LibVersion}{$Tid});
10057 }
10058 }
10059 }
10060
10061 foreach my $Tid (keys(%Delete))
10062 {
10063 delete($TypeInfo{$LibVersion}{$Tid});
10064 }
10065}
10066
10067sub check_Completeness($$)
10068{
10069 my ($Info, $LibVersion) = @_;
10070
10071 # data types
10072 if(defined $Info->{"Memb"})
10073 {
10074 foreach my $Pos (keys(%{$Info->{"Memb"}}))
10075 {
10076 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
10077 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
10078 }
10079 }
10080 }
10081 if(defined $Info->{"Base"})
10082 {
10083 foreach my $Bid (keys(%{$Info->{"Base"}})) {
10084 check_TypeInfo($Bid, $LibVersion);
10085 }
10086 }
10087 if(defined $Info->{"BaseType"}) {
10088 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
10089 }
10090 if(defined $Info->{"TParam"})
10091 {
10092 foreach my $Pos (keys(%{$Info->{"TParam"}}))
10093 {
10094 my $TName = $Info->{"TParam"}{$Pos}{"name"};
10095 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
10096 next;
10097 }
10098 if($TName eq "_BoolType") {
10099 next;
10100 }
10101 if($TName=~/\Asizeof\(/) {
10102 next;
10103 }
10104 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
10105 check_TypeInfo($Tid, $LibVersion);
10106 }
10107 else
10108 {
10109 if(defined $Debug) {
10110 printMsg("WARNING", "missed type $TName");
10111 }
10112 }
10113 }
10114 }
10115
10116 # symbols
10117 if(defined $Info->{"Param"})
10118 {
10119 foreach my $Pos (keys(%{$Info->{"Param"}}))
10120 {
10121 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10122 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10123 }
10124 }
10125 }
10126 if(defined $Info->{"Return"}) {
10127 check_TypeInfo($Info->{"Return"}, $LibVersion);
10128 }
10129 if(defined $Info->{"Class"}) {
10130 check_TypeInfo($Info->{"Class"}, $LibVersion);
10131 }
10132}
10133
10134sub check_TypeInfo($$)
10135{
10136 my ($Tid, $LibVersion) = @_;
10137
10138 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10139 return;
10140 }
10141 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10142
10143 if(defined $TypeInfo{$LibVersion}{$Tid})
10144 {
10145 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10146 printMsg("ERROR", "missed type name ($Tid)");
10147 }
10148 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10149 }
10150 else {
10151 printMsg("ERROR", "missed type id $Tid");
10152 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010153}
10154
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010155sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010156{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010157 my ($TypeId, $LibVersion) = @_;
10158 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010159 if($Type{"Type"} eq "Typedef")
10160 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010161 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010162 if($Base{"Type"}=~/Class|Struct/)
10163 {
10164 if($Type{"Name"} eq $Base{"Name"}) {
10165 return 1;
10166 }
10167 elsif($Type{"Name"}=~/::(\w+)\Z/)
10168 {
10169 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10170 { # QPointer<QWidget>::QPointer
10171 return 1;
10172 }
10173 }
10174 }
10175 }
10176 return 0;
10177}
10178
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010179sub addExtension($)
10180{
10181 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010182 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010183 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010184 if(selectType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010185 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010186 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10187 $TName=~s/\A(struct|union|class|enum) //;
10188 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010189
10190 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10191 "Header" => "extended.h",
10192 "ShortName" => $Symbol,
10193 "MnglName" => $Symbol,
10194 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10195 );
10196
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010197 $ExtendedSymbols{$Symbol} = 1;
10198 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10199 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010200 }
10201 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010202 $ExtendedSymbols{"external_func_0"} = 1;
10203 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10204 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010205}
10206
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010207sub findMethod($$$)
10208{
10209 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010210 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010211 {
10212 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10213 return $VirtMethodInClass;
10214 }
10215 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10216 return $VirtMethodInBaseClasses;
10217 }
10218 }
10219 return "";
10220}
10221
10222sub findMethod_Class($$$)
10223{
10224 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010225 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010226 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10227 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10228 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10229 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10230 { # search for interface with the same parameters suffix (overridden)
10231 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10232 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010233 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10234 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010235 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10236 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010237 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10238 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10239 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10240 return $Candidate;
10241 }
10242 }
10243 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010244 else
10245 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010246 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10247 return $Candidate;
10248 }
10249 }
10250 }
10251 }
10252 return "";
10253}
10254
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010255sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010256{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010257 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010258 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010259 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010260 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10261 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010262 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010263 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010264 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010265 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10266 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010267 { # pure virtual D2-destructors are marked as "virt" in the dump
10268 # virtual D2-destructors are NOT marked as "virt" in the dump
10269 # both destructors are not presented in the v-table
10270 next;
10271 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010272 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010273 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10274 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010275 }
10276}
10277
10278sub registerOverriding($)
10279{
10280 my $LibVersion = $_[0];
10281 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010282 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010283 foreach my $ClassName (@Classes)
10284 {
10285 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10286 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010287 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10288 { # pure virtuals
10289 next;
10290 }
10291 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10292 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010293 {
10294 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10295 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10296 { # both overridden virtual methods
10297 # and implemented pure virtual methods
10298 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10299 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10300 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10301 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010302 }
10303 }
10304 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10305 delete($VirtualTable{$LibVersion}{$ClassName});
10306 }
10307 }
10308}
10309
10310sub setVirtFuncPositions($)
10311{
10312 my $LibVersion = $_[0];
10313 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10314 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010315 my ($Num, $Rel) = (1, 0);
10316
10317 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010318 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010319 if($UsedDump{$LibVersion}{"DWARF"}) {
10320 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10321 }
10322 else {
10323 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10324 }
10325 foreach my $VirtFunc (@Funcs)
10326 {
10327 if($UsedDump{$LibVersion}{"DWARF"}) {
10328 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10329 }
10330 else {
10331 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10332 }
10333
10334 # set relative positions
10335 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10336 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10337 { # relative position excluding added and removed virtual functions
10338 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10339 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10340 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10341 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010342 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010343 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010344 }
10345 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010346 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010347 {
10348 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010349 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010350 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010351 }
10352 }
10353}
10354
10355sub get_sub_classes($$$)
10356{
10357 my ($ClassId, $LibVersion, $Recursive) = @_;
10358 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10359 my @Subs = ();
10360 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10361 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010362 if($Recursive)
10363 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010364 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10365 push(@Subs, $SubSubId);
10366 }
10367 }
10368 push(@Subs, $SubId);
10369 }
10370 return @Subs;
10371}
10372
10373sub get_base_classes($$$)
10374{
10375 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010376 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010377 return () if(not defined $ClassType{"Base"});
10378 my @Bases = ();
10379 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10380 keys(%{$ClassType{"Base"}}))
10381 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010382 if($Recursive)
10383 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010384 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10385 push(@Bases, $SubBaseId);
10386 }
10387 }
10388 push(@Bases, $BaseId);
10389 }
10390 return @Bases;
10391}
10392
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010393sub getVTable_Model($$)
10394{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010395 my ($ClassId, $LibVersion) = @_;
10396 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10397 my @Elements = ();
10398 foreach my $BaseId (@Bases, $ClassId)
10399 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010400 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010401 {
10402 if(defined $VirtualTable{$LibVersion}{$BName})
10403 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010404 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10405 if($UsedDump{$LibVersion}{"DWARF"}) {
10406 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10407 }
10408 else {
10409 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10410 }
10411 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010412 push(@Elements, $VFunc);
10413 }
10414 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010415 }
10416 }
10417 return @Elements;
10418}
10419
10420sub getVShift($$)
10421{
10422 my ($ClassId, $LibVersion) = @_;
10423 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10424 my $VShift = 0;
10425 foreach my $BaseId (@Bases)
10426 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010427 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010428 {
10429 if(defined $VirtualTable{$LibVersion}{$BName}) {
10430 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10431 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010432 }
10433 }
10434 return $VShift;
10435}
10436
10437sub getShift($$)
10438{
10439 my ($ClassId, $LibVersion) = @_;
10440 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10441 my $Shift = 0;
10442 foreach my $BaseId (@Bases)
10443 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010444 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010445 {
10446 if($Size!=1)
10447 { # not empty base class
10448 $Shift+=$Size;
10449 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010450 }
10451 }
10452 return $Shift;
10453}
10454
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010455sub getVTable_Size($$)
10456{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010457 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010458 my $Size = 0;
10459 # three approaches
10460 if(not $Size)
10461 { # real size
10462 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10463 $Size = keys(%VTable);
10464 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010465 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010466 if(not $Size)
10467 { # shared library symbol size
10468 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10469 $Size /= $WORD_SIZE{$LibVersion};
10470 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010471 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010472 if(not $Size)
10473 { # model size
10474 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10475 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10476 }
10477 }
10478 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010479}
10480
10481sub isCopyingClass($$)
10482{
10483 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010484 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010485}
10486
10487sub isLeafClass($$)
10488{
10489 my ($ClassId, $LibVersion) = @_;
10490 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10491}
10492
10493sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010494{ # check structured type for public fields
10495 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010496}
10497
10498sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010499{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010500 my ($TypePtr, $Skip, $Start, $End) = @_;
10501 return 0 if(not $TypePtr);
10502 if($End==-1) {
10503 $End = keys(%{$TypePtr->{"Memb"}})-1;
10504 }
10505 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}}))
10506 {
10507 if($Skip and $Skip->{$MemPos})
10508 { # skip removed/added fields
10509 next;
10510 }
10511 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10512 {
10513 if(isPublic($TypePtr, $MemPos)) {
10514 return ($MemPos+1);
10515 }
10516 }
10517 }
10518 return 0;
10519}
10520
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010521sub isReserved($)
10522{ # reserved fields == private
10523 my $MName = $_[0];
10524 if($MName=~/reserved|padding|f_spare/i) {
10525 return 1;
10526 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040010527 if($MName=~/\A[_]*(spare|pad|unused|dummy)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010528 return 1;
10529 }
10530 if($MName=~/(pad\d+)/i) {
10531 return 1;
10532 }
10533 return 0;
10534}
10535
10536sub isPublic($$)
10537{
10538 my ($TypePtr, $FieldPos) = @_;
10539 return 0 if(not $TypePtr);
10540 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10541 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10542 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10543 { # by name in C language
10544 # FIXME: add other methods to detect private members
10545 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10546 if($MName=~/priv|abidata|parent_object/i)
10547 { # C-styled private data
10548 return 0;
10549 }
10550 if(lc($MName) eq "abi")
10551 { # ABI information/reserved field
10552 return 0;
10553 }
10554 if(isReserved($MName))
10555 { # reserved fields
10556 return 0;
10557 }
10558 return 1;
10559 }
10560 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10561 { # by access in C++ language
10562 return 1;
10563 }
10564 return 0;
10565}
10566
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010567sub getVTable_Real($$)
10568{
10569 my ($ClassName, $LibVersion) = @_;
10570 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10571 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010572 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010573 if(defined $Type{"VTable"}) {
10574 return %{$Type{"VTable"}};
10575 }
10576 }
10577 return ();
10578}
10579
10580sub cmpVTables($)
10581{
10582 my $ClassName = $_[0];
10583 my $Res = cmpVTables_Real($ClassName, 1);
10584 if($Res==-1) {
10585 $Res = cmpVTables_Model($ClassName);
10586 }
10587 return $Res;
10588}
10589
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010590sub cmpVTables_Model($)
10591{
10592 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010593 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010594 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010595 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010596 return 1;
10597 }
10598 }
10599 return 0;
10600}
10601
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010602sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010603{
10604 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010605 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10606 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010607 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010608 my %VTable_Old = getVTable_Real($ClassName, 1);
10609 my %VTable_New = getVTable_Real($ClassName, 2);
10610 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010611 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010612 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010613 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010614 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010615 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10616 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010617 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010618 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010619 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010620 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010621 my $Entry1 = $VTable_Old{$Offset};
10622 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010623 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010624 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010625 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010626 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010627 $Entry1 = simpleVEntry($Entry1);
10628 $Entry2 = simpleVEntry($Entry2);
10629 if($Entry1 ne $Entry2)
10630 { # register as changed
10631 if($Entry1=~/::([^:]+)\Z/)
10632 {
10633 my $M1 = $1;
10634 if($Entry2=~/::([^:]+)\Z/)
10635 {
10636 my $M2 = $1;
10637 if($M1 eq $M2)
10638 { # overridden
10639 next;
10640 }
10641 }
10642 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010643 if(differentDumps("G"))
10644 {
10645 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10646 {
10647 # GCC 4.6.1: -0x00000000000000010
10648 # GCC 4.7.0: -16
10649 next;
10650 }
10651 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010652 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010653 }
10654 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010655 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010656}
10657
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010658sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010659{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010660 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010661 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10662 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010663 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010664 { # already registered
10665 next;
10666 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010667 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010668 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010669 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010670 foreach my $Symbol (@Affected)
10671 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010672 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010673 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010674 "Target"=>$ClassName);
10675 }
10676 }
10677 }
10678}
10679
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010680sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010681{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010682 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010683 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010684 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010685 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010686 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010687 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010688 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010689 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010690 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010691 if($TName_Tid{1}{$ClassName}
10692 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010693 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010694 if(defined $CompleteSignature{1}{$Symbol}
10695 and $CompleteSignature{1}{$Symbol}{"Virt"})
10696 { # override some method in v.1
10697 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010698 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010699 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010700 }
10701 }
10702 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010703 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010704 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010705 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010706 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010707 if($TName_Tid{2}{$ClassName}
10708 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010709 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010710 if(defined $CompleteSignature{2}{$Symbol}
10711 and $CompleteSignature{2}{$Symbol}{"Virt"})
10712 { # override some method in v.2
10713 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010714 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010715 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010716 }
10717 }
10718 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010719 if($Level eq "Binary")
10720 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010721 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010722 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10723 { # check replacements, including pure virtual methods
10724 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10725 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010726 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010727 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10728 if($AddedPos==$RemovedPos)
10729 {
10730 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10731 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10732 last; # other methods will be reported as "added" or "removed"
10733 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010734 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010735 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10736 {
10737 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10738 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010739 next;
10740 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010741 my $ProblemType = "Virtual_Replacement";
10742 my @Affected = ($RemovedVFunc);
10743 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10744 { # pure methods
10745 if(not isUsedClass($ClassId, 1, $Level))
10746 { # not a parameter of some exported method
10747 next;
10748 }
10749 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010750
10751 # affected all methods (both virtual and non-virtual ones)
10752 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10753 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010754 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010755 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010756 foreach my $AffectedInt (@Affected)
10757 {
10758 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10759 { # affected exported methods only
10760 next;
10761 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010762 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10763 next;
10764 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010765 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10766 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010767 "Target"=>get_Signature($AddedVFunc, 2),
10768 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10769 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010770 }
10771 }
10772 }
10773 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010774 if(not checkDump(1, "2.0")
10775 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010776 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010777 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010778 return;
10779 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010780 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010781 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010782 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010783 next if(not $ClassId_Old);
10784 if(not isCreatable($ClassId_Old, 1))
10785 { # skip classes without public constructors (including auto-generated)
10786 # example: class has only a private exported or private inline constructor
10787 next;
10788 }
10789 if($ClassName=~/>/)
10790 { # skip affected template instances
10791 next;
10792 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010793 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010794 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010795 if(not $ClassId_New) {
10796 next;
10797 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010798 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010799 if($Class_New{"Type"}!~/Class|Struct/)
10800 { # became typedef
10801 if($Level eq "Binary") {
10802 next;
10803 }
10804 if($Level eq "Source")
10805 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010806 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010807 if($Class_New{"Type"}!~/Class|Struct/) {
10808 next;
10809 }
10810 $ClassId_New = $Class_New{"Tid"};
10811 }
10812 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010813 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10814 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 +040010815
10816 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10817 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10818
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010819 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010820 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10821 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010822 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10823 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010824 my $Shift_Old = getShift($ClassId_Old, 1);
10825 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010826 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010827 my ($Added, $Removed) = (0, 0);
10828 my @StableBases_Old = ();
10829 foreach my $BaseId (@Bases_Old)
10830 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010831 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010832 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010833 push(@StableBases_Old, $BaseId);
10834 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010835 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010836 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010837 { # removed base
10838 # excluding namespace::SomeClass to SomeClass renaming
10839 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010840 if($Level eq "Binary")
10841 { # Binary-level
10842 if($Shift_Old ne $Shift_New)
10843 { # affected fields
10844 if(havePubFields(\%Class_Old)) {
10845 $ProblemKind .= "_And_Shift";
10846 }
10847 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10848 $ProblemKind .= "_And_Size";
10849 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010850 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010851 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10852 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010853 { # affected v-table
10854 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010855 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010856 }
10857 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010858 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010859 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10860 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010861 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10862 {
10863 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10864 if($ProblemKind=~/VTable/) {
10865 $VTableChanged_M{$SubName}=1;
10866 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010867 }
10868 }
10869 foreach my $Interface (@Affected)
10870 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010871 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10872 next;
10873 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010874 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010875 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010876 "Target"=>$BaseName,
10877 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10878 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10879 "Shift"=>abs($Shift_New-$Shift_Old) );
10880 }
10881 $Removed+=1;
10882 }
10883 }
10884 my @StableBases_New = ();
10885 foreach my $BaseId (@Bases_New)
10886 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010887 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010888 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010889 push(@StableBases_New, $BaseId);
10890 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010891 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010892 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010893 { # added base
10894 # excluding namespace::SomeClass to SomeClass renaming
10895 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010896 if($Level eq "Binary")
10897 { # Binary-level
10898 if($Shift_Old ne $Shift_New)
10899 { # affected fields
10900 if(havePubFields(\%Class_Old)) {
10901 $ProblemKind .= "_And_Shift";
10902 }
10903 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10904 $ProblemKind .= "_And_Size";
10905 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010906 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010907 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10908 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010909 { # affected v-table
10910 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010911 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010912 }
10913 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010914 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010915 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10916 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010917 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10918 {
10919 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10920 if($ProblemKind=~/VTable/) {
10921 $VTableChanged_M{$SubName}=1;
10922 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010923 }
10924 }
10925 foreach my $Interface (@Affected)
10926 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010927 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10928 next;
10929 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010930 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010931 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010932 "Target"=>$BaseName,
10933 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10934 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10935 "Shift"=>abs($Shift_New-$Shift_Old) );
10936 }
10937 $Added+=1;
10938 }
10939 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010940 if($Level eq "Binary")
10941 { # Binary-level
10942 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010943 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10944 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010945 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010946 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010947 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010948 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010949 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010950 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10951 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010952 if($NewPos!=$OldPos)
10953 { # changed position of the base class
10954 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010955 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010956 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10957 next;
10958 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010959 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10960 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010961 "Target"=>$BaseName,
10962 "Old_Value"=>$OldPos-1,
10963 "New_Value"=>$NewPos-1 );
10964 }
10965 }
10966 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10967 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10968 { # became non-virtual base
10969 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10970 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010971 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10972 next;
10973 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010974 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10975 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010976 "Target"=>$BaseName );
10977 }
10978 }
10979 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10980 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10981 { # became virtual base
10982 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10983 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010984 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10985 next;
10986 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010987 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10988 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010989 "Target"=>$BaseName );
10990 }
10991 }
10992 }
10993 }
10994 # detect size changes in base classes
10995 if($Shift_Old!=$Shift_New)
10996 { # size of allocable class
10997 foreach my $BaseId (@StableBases_Old)
10998 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010999 my %BaseType = get_Type($BaseId, 1);
11000 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011001 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011002 if($Size_Old ne $Size_New
11003 and $Size_Old and $Size_New)
11004 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011005 my $ProblemType = undef;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011006 if(isCopyingClass($BaseId, 1)) {
11007 $ProblemType = "Size_Of_Copying_Class";
11008 }
11009 elsif($AllocableClass{1}{$BaseType{"Name"}})
11010 {
11011 if($Size_New>$Size_Old)
11012 { # increased size
11013 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011014 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011015 else
11016 { # decreased size
11017 $ProblemType = "Size_Of_Allocable_Class_Decreased";
11018 if(not havePubFields(\%Class_Old))
11019 { # affected class has no public members
11020 next;
11021 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011022 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011023 }
11024 next if(not $ProblemType);
11025 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
11026 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011027 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
11028 next;
11029 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011030 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
11031 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011032 "Target"=>$BaseType{"Name"},
11033 "Old_Size"=>$Size_Old*$BYTE_SIZE,
11034 "New_Size"=>$Size_New*$BYTE_SIZE );
11035 }
11036 }
11037 }
11038 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011039 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011040 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011041 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011042 { # compare virtual tables size in base classes
11043 my $VShift_Old = getVShift($ClassId_Old, 1);
11044 my $VShift_New = getVShift($ClassId_New, 2);
11045 if($VShift_Old ne $VShift_New)
11046 { # changes in the base class or changes in the list of base classes
11047 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
11048 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
11049 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011050 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011051 foreach my $BaseId (@AllBases_Old)
11052 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011053 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011054 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011055 { # lost base
11056 next;
11057 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011058 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
11059 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011060 if($VSize_Old!=$VSize_New)
11061 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011062 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011063 { # TODO: affected non-virtual methods?
11064 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011065 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
11066 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011067 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011068 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011069 { # skip interfaces that have not changed the absolute virtual position
11070 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011071 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011072 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
11073 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011074 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011075 $VTableChanged_M{$BaseType{"Name"}} = 1;
11076 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011077 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
11078 { # the reason of the layout change: added virtual functions
11079 next if($VirtualReplacement{$VirtFunc});
11080 my $ProblemType = "Added_Virtual_Method";
11081 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
11082 $ProblemType = "Added_Pure_Virtual_Method";
11083 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011084 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011085 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011086 "Target"=>get_Signature($VirtFunc, 2) );
11087 }
11088 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
11089 { # the reason of the layout change: removed virtual functions
11090 next if($VirtualReplacement{$VirtFunc});
11091 my $ProblemType = "Removed_Virtual_Method";
11092 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11093 $ProblemType = "Removed_Pure_Virtual_Method";
11094 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011095 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011096 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011097 "Target"=>get_Signature($VirtFunc, 1) );
11098 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011099 }
11100 }
11101 }
11102 }
11103 }
11104 }
11105 }
11106}
11107
11108sub isCreatable($$)
11109{
11110 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011111 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011112 or isCopyingClass($ClassId, $LibVersion)) {
11113 return 1;
11114 }
11115 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11116 { # Fix for incomplete data: if this class has
11117 # a base class then it should also has a constructor
11118 return 1;
11119 }
11120 if($ReturnedClass{$LibVersion}{$ClassId})
11121 { # returned by some method of this class
11122 # or any other class
11123 return 1;
11124 }
11125 return 0;
11126}
11127
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011128sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011129{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011130 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011131 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11132 { # parameter of some exported method
11133 return 1;
11134 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011135 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11136 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011137 { # method from target class
11138 return 1;
11139 }
11140 return 0;
11141}
11142
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011143sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011144{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011145 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011146 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011147 # - virtual
11148 # - pure-virtual
11149 # - non-virtual
11150 if($CompleteSignature{1}{$Interface}{"Data"})
11151 { # global data is not affected
11152 return;
11153 }
11154 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011155 if(not $Class_Id) {
11156 return;
11157 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011158 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011159 if(cmpVTables_Real($CName, 1)==0)
11160 { # no changes
11161 return;
11162 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011163 $CheckedTypes{$Level}{$CName} = 1;
11164 if($Level eq "Binary")
11165 { # Binary-level
11166 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11167 and not isUsedClass($Class_Id, 1, $Level))
11168 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011169 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011170 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011171 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011172 }
11173 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11174 {
11175 if(defined $VirtualTable{2}{$CName}{$Func}
11176 and defined $CompleteSignature{2}{$Func})
11177 {
11178 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11179 and $CompleteSignature{2}{$Func}{"PureVirt"})
11180 { # became pure virtual
11181 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11182 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011183 "Target"=>get_Signature_M($Func, 1) );
11184 $VTableChanged_M{$CName} = 1;
11185 }
11186 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11187 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11188 { # became non-pure virtual
11189 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11190 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011191 "Target"=>get_Signature_M($Func, 1) );
11192 $VTableChanged_M{$CName} = 1;
11193 }
11194 }
11195 }
11196 if($Level eq "Binary")
11197 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011198 # check virtual table structure
11199 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11200 {
11201 next if($Interface eq $AddedVFunc);
11202 next if($VirtualReplacement{$AddedVFunc});
11203 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11204 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11205 { # pure virtual methods affect all others (virtual and non-virtual)
11206 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011207 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011208 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011209 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011210 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011211 elsif(not defined $VirtualTable{1}{$CName}
11212 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011213 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011214 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011215 { # became polymorphous class, added v-table pointer
11216 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011217 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011218 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011219 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011220 }
11221 else
11222 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011223 my $VSize_Old = getVTable_Size($CName, 1);
11224 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011225 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011226 if(isCopyingClass($Class_Id, 1))
11227 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11228 my $ProblemType = "Added_Virtual_Method";
11229 if(isLeafClass($Class_Id, 1)) {
11230 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11231 }
11232 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11233 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011234 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011235 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011236 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011237 else
11238 {
11239 my $ProblemType = "Added_Virtual_Method";
11240 if(isLeafClass($Class_Id, 1)) {
11241 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11242 }
11243 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11244 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011245 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011246 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011247 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011248 }
11249 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011250 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11251 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011252 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011253 if(defined $VirtualTable{1}{$CName}
11254 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011255 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011256 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11257 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011258
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011259 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011260 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011261 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11262 foreach my $ASymbol (@Affected)
11263 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011264 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11265 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011266 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011267 next;
11268 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011269 }
11270 $CheckedSymbols{$Level}{$ASymbol} = 1;
11271 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11272 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011273 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011274 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011275 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011276 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011277 }
11278 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011279 else {
11280 # safe
11281 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011282 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011283 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11284 {
11285 next if($VirtualReplacement{$RemovedVFunc});
11286 if($RemovedVFunc eq $Interface
11287 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11288 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011289 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011290 next;
11291 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011292 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011293 { # became non-polymorphous class, removed v-table pointer
11294 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11295 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011296 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011297 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011298 }
11299 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11300 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11301 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011302 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011303 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011304 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11305 next;
11306 }
11307 my $VPos_New = -1;
11308 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011309 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011310 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11311 }
11312 else
11313 {
11314 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011315 next;
11316 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011317 }
11318 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11319 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11320 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11321 {
11322 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11323 foreach my $ASymbol (@Affected)
11324 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011325 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11326 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011327 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011328 next;
11329 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011330 }
11331 my $ProblemType = "Removed_Virtual_Method";
11332 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11333 $ProblemType = "Removed_Pure_Virtual_Method";
11334 }
11335 $CheckedSymbols{$Level}{$ASymbol} = 1;
11336 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11337 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011338 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011339 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011340 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011341 }
11342 }
11343 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011344 }
11345 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011346 else
11347 { # Source-level
11348 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011349 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011350 next if($Interface eq $AddedVFunc);
11351 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011352 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011353 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11354 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011355 "Target"=>get_Signature($AddedVFunc, 2) );
11356 }
11357 }
11358 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11359 {
11360 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11361 {
11362 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11363 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011364 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011365 }
11366 }
11367 }
11368}
11369
11370sub find_MemberPair_Pos_byName($$)
11371{
11372 my ($Member_Name, $Pair_Type) = @_;
11373 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11374 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11375 {
11376 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11377 {
11378 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11379 $Name=~s/\A[_]+|[_]+\Z//g;
11380 if($Name eq $Member_Name) {
11381 return $MemberPair_Pos;
11382 }
11383 }
11384 }
11385 return "lost";
11386}
11387
11388sub find_MemberPair_Pos_byVal($$)
11389{
11390 my ($Member_Value, $Pair_Type) = @_;
11391 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11392 {
11393 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11394 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11395 return $MemberPair_Pos;
11396 }
11397 }
11398 return "lost";
11399}
11400
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011401sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011402{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011403 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011404 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011405 if( $_->{"T1"} eq $_[0]
11406 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011407 {
11408 return 1;
11409 }
11410 }
11411 return 0;
11412}
11413
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011414sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011415{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011416 my %IDs = (
11417 "T1" => $_[0],
11418 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011419 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011420 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011421}
11422
11423sub isRenamed($$$$$)
11424{
11425 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11426 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11427 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011428 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011429 if(not defined $Type2->{"Memb"}{$MemPos}) {
11430 return "";
11431 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011432 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011433 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011434
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011435 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11436 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011437 if($MemberPair_Pos_Rev eq "lost")
11438 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011439 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11440 { # base type match
11441 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011442 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011443 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11444 { # exact type match
11445 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011446 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011447 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11448 { # size match
11449 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011450 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011451 if(isReserved($Pair_Name))
11452 { # reserved fields
11453 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011454 }
11455 }
11456 return "";
11457}
11458
11459sub isLastElem($$)
11460{
11461 my ($Pos, $TypeRef) = @_;
11462 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11463 if($Name=~/last|count|max|total/i)
11464 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11465 return 1;
11466 }
11467 elsif($Name=~/END|NLIMITS\Z/)
11468 { # __RLIMIT_NLIMITS
11469 return 1;
11470 }
11471 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11472 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11473 { # NImageFormats, NColorRoles
11474 return 1;
11475 }
11476 return 0;
11477}
11478
11479sub nonComparable($$)
11480{
11481 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011482
11483 my $N1 = $T1->{"Name"};
11484 my $N2 = $T2->{"Name"};
11485
11486 $N1=~s/\A(struct|union|enum) //;
11487 $N2=~s/\A(struct|union|enum) //;
11488
11489 if($N1 ne $N2
11490 and not isAnon($N1)
11491 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011492 { # different names
11493 if($T1->{"Type"} ne "Pointer"
11494 or $T2->{"Type"} ne "Pointer")
11495 { # compare base types
11496 return 1;
11497 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011498 if($N1!~/\Avoid\s*\*/
11499 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011500 {
11501 return 1;
11502 }
11503 }
11504 elsif($T1->{"Type"} ne $T2->{"Type"})
11505 { # different types
11506 if($T1->{"Type"} eq "Class"
11507 and $T2->{"Type"} eq "Struct")
11508 { # "class" to "struct"
11509 return 0;
11510 }
11511 elsif($T2->{"Type"} eq "Class"
11512 and $T1->{"Type"} eq "Struct")
11513 { # "struct" to "class"
11514 return 0;
11515 }
11516 else
11517 { # "class" to "enum"
11518 # "union" to "class"
11519 # ...
11520 return 1;
11521 }
11522 }
11523 return 0;
11524}
11525
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011526sub isOpaque($)
11527{
11528 my $T = $_[0];
11529 if(not defined $T->{"Memb"})
11530 {
11531 return 1;
11532 }
11533 return 0;
11534}
11535
11536sub removeVPtr($)
11537{ # support for old ABI dumps
11538 my $TPtr = $_[0];
11539 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11540 if($#Pos>=1)
11541 {
11542 foreach my $Pos (0 .. $#Pos-1)
11543 {
11544 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11545 }
11546 delete($TPtr->{"Memb"}{$#Pos});
11547 }
11548}
11549
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011550sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011551{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011552 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011553 return {} if(not $Type1_Id or not $Type2_Id);
11554
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011555 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011556 { # already merged
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011557 return $Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011558 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011559
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011560 my %Type1 = get_Type($Type1_Id, 1);
11561 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011562 if(not $Type1{"Name"} or not $Type2{"Name"}) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011563 return {};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011564 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011565
11566 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011567 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11568 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011569
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011570 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11571
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011572 my %SubProblems = ();
11573
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011574 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11575 {
11576 if($Type1_Pure{"Type"}=~/Struct|Union/
11577 and $Type2_Pure{"Type"}=~/Struct|Union/)
11578 {
11579 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11580 {
11581 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11582 "Target"=>$Type1_Pure{"Name"},
11583 "Type_Name"=>$Type1_Pure{"Name"} );
11584
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011585 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011586 }
11587 }
11588 }
11589
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011590 if(not $Type1_Pure{"Size"}
11591 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011592 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011593 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11594 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11595 { # NOTE: template instances have no size
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011596 return {};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011597 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011598 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011599 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011600 { # skip recursive declarations
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011601 return {};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011602 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011603 return {} if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11604 return {} if($SkipTypes{1}{$Type1_Pure{"Name"}});
11605 return {} if($SkipTypes{1}{$Type1{"Name"}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011606
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011607 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11608 { # support for old ABI dumps
11609 # _vptr field added in 3.0
11610 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11611 {
11612 if(defined $Type2_Pure{"Memb"}
11613 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11614 {
11615 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11616 delete($Type2_Pure{"Memb"}{0});
11617 }
11618 else {
11619 removeVPtr(\%Type2_Pure);
11620 }
11621 }
11622 }
11623 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11624 {
11625 if(defined $Type1_Pure{"Memb"}
11626 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11627 {
11628 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11629 delete($Type1_Pure{"Memb"}{0});
11630 }
11631 else {
11632 removeVPtr(\%Type1_Pure);
11633 }
11634 }
11635 }
11636 }
11637
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011638 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11639 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011640
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011641 if(not $UseOldDumps and %Typedef_1 and %Typedef_2
11642 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11643 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011644 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011645 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11646 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011647 if($Base_1{"Name"} ne $Base_2{"Name"})
11648 {
11649 if(differentDumps("G")
11650 or differentDumps("V"))
11651 { # different GCC versions or different dumps
11652 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11653 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11654 # std::__va_list and __va_list
11655 $Base_1{"Name"}=~s/\A(\w+::)+//;
11656 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011657 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11658 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011659 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011660 }
11661 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11662 and $Base_1{"Name"} ne $Base_2{"Name"})
11663 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011664 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011665 and $Type1{"Size"} and $Type2{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011666 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011667 {
11668 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11669 "Target"=>$Typedef_1{"Name"},
11670 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011671 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11672 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11673 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011674 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11675 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011676 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011677 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011678 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11679 {
11680 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11681 "Target"=>$Typedef_1{"Name"},
11682 "Type_Name"=>$Typedef_1{"Name"},
11683 "Old_Value"=>$Base_1{"Name"},
11684 "New_Value"=>$Base_2{"Name"} );
11685 }
11686 else
11687 {
11688 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11689 "Target"=>$Typedef_1{"Name"},
11690 "Type_Name"=>$Typedef_1{"Name"},
11691 "Old_Value"=>$Base_1{"Name"},
11692 "New_Value"=>$Base_2{"Name"} );
11693 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011694 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011695 }
11696 }
11697 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11698 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011699 my $TT1 = $Type1_Pure{"Type"};
11700 my $TT2 = $Type2_Pure{"Type"};
11701
11702 if($TT1 ne $TT2
11703 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011704 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011705 my $Short1 = $Type1_Pure{"Name"};
11706 my $Short2 = $Type2_Pure{"Name"};
11707
11708 $Short1=~s/\A\Q$TT1\E //ig;
11709 $Short2=~s/\A\Q$TT2\E //ig;
11710
11711 if($Short1 eq $Short2)
11712 {
11713 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11714 "Target"=>$Type1_Pure{"Name"},
11715 "Type_Name"=>$Type1_Pure{"Name"},
11716 "Old_Value"=>lc($Type1_Pure{"Type"}),
11717 "New_Value"=>lc($Type2_Pure{"Type"}) );
11718 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011719 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011720 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011721 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011722 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011723 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11724 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11725 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11726 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011727 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040011728 and $Type1_Pure{"Size"} and $Type2_Pure{"Size"}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011729 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011730 {
11731 my $ProblemKind = "DataType_Size";
11732 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011733 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011734 {
11735 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11736 $ProblemKind = "Size_Of_Copying_Class";
11737 }
11738 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11739 {
11740 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11741 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11742 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011743 else
11744 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011745 # descreased size of allocable class
11746 # it has no special effects
11747 }
11748 }
11749 }
11750 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11751 "Target"=>$Type1_Pure{"Name"},
11752 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011753 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011754 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011755 }
11756 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011757 if(defined $Type1_Pure{"BaseType"}
11758 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011759 { # checking base types
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011760 my $Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
11761 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011762 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040011763 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}})) {
11764 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011765 }
11766 }
11767 }
11768 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11769 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11770 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11771 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11772 { # detect removed and renamed fields
11773 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11774 next if(not $Member_Name);
11775 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);
11776 if($MemberPair_Pos eq "lost")
11777 {
11778 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11779 {
11780 if(isUnnamed($Member_Name))
11781 { # support for old-version dumps
11782 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011783 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011784 next;
11785 }
11786 }
11787 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11788 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011789 $RenamedField{$Member_Pos} = $RenamedTo;
11790 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011791 }
11792 else
11793 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011794 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011795 }
11796 }
11797 elsif($Type1_Pure{"Type"} eq "Enum")
11798 {
11799 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11800 next if($Member_Value1 eq "");
11801 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11802 if($MemberPair_Pos ne "lost")
11803 { # renamed
11804 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11805 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11806 if($MemberPair_Pos_Rev eq "lost")
11807 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011808 $RenamedField{$Member_Pos} = $RenamedTo;
11809 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011810 }
11811 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011812 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011813 }
11814 }
11815 else
11816 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011817 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011818 }
11819 }
11820 }
11821 else
11822 { # related
11823 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11824 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11825 }
11826 }
11827 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11828 { # detect added fields
11829 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11830 next if(not $Member_Name);
11831 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);
11832 if($MemberPair_Pos eq "lost")
11833 {
11834 if(isUnnamed($Member_Name))
11835 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011836 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011837 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011838 next;
11839 }
11840 }
11841 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11842 {
11843 if(not $RenamedField_Rev{$Member_Pos})
11844 { # added
11845 $AddedField{$Member_Pos}=1;
11846 }
11847 }
11848 }
11849 }
11850 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11851 { # detect moved fields
11852 my (%RelPos, %RelPosName, %AbsPos) = ();
11853 my $Pos = 0;
11854 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11855 { # relative positions in 1st version
11856 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11857 next if(not $Member_Name);
11858 if(not $RemovedField{$Member_Pos})
11859 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011860 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011861 $RelPosName{1}{$Pos} = $Member_Name;
11862 $AbsPos{1}{$Pos++} = $Member_Pos;
11863 }
11864 }
11865 $Pos = 0;
11866 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11867 { # relative positions in 2nd version
11868 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11869 next if(not $Member_Name);
11870 if(not $AddedField{$Member_Pos})
11871 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011872 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011873 $RelPosName{2}{$Pos} = $Member_Name;
11874 $AbsPos{2}{$Pos++} = $Member_Pos;
11875 }
11876 }
11877 foreach my $Member_Name (keys(%{$RelPos{1}}))
11878 {
11879 my $RPos1 = $RelPos{1}{$Member_Name};
11880 my $AbsPos1 = $NameToPosA{$Member_Name};
11881 my $Member_Name2 = $Member_Name;
11882 if(my $RenamedTo = $RenamedField{$AbsPos1})
11883 { # renamed
11884 $Member_Name2 = $RenamedTo;
11885 }
11886 my $RPos2 = $RelPos{2}{$Member_Name2};
11887 if($RPos2 ne "" and $RPos1 ne $RPos2)
11888 { # different relative positions
11889 my $AbsPos2 = $NameToPosB{$Member_Name2};
11890 if($AbsPos1 ne $AbsPos2)
11891 { # different absolute positions
11892 my $ProblemType = "Moved_Field";
11893 if(not isPublic(\%Type1_Pure, $AbsPos1))
11894 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011895 if($Level eq "Source") {
11896 next;
11897 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011898 $ProblemType = "Moved_Private_Field";
11899 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011900 if($Level eq "Binary"
11901 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011902 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011903 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011904 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011905 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011906 if($MemSize1 ne $MemSize2) {
11907 $ProblemType .= "_And_Size";
11908 }
11909 }
11910 if($ProblemType eq "Moved_Private_Field") {
11911 next;
11912 }
11913 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11914 "Target"=>$Member_Name,
11915 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011916 "Old_Value"=>$RPos1,
11917 "New_Value"=>$RPos2 );
11918 }
11919 }
11920 }
11921 }
11922 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011923 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011924 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11925 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011926 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011927 if(my $RenamedTo = $RenamedField{$Member_Pos})
11928 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011929 if(defined $Constants{2}{$Member_Name})
11930 {
11931 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11932 { # define OLD NEW
11933 next; # Safe
11934 }
11935 }
11936
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011937 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11938 {
11939 if(isPublic(\%Type1_Pure, $Member_Pos))
11940 {
11941 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11942 "Target"=>$Member_Name,
11943 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011944 "Old_Value"=>$Member_Name,
11945 "New_Value"=>$RenamedTo );
11946 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011947 elsif(isReserved($Member_Name))
11948 {
11949 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11950 "Target"=>$Member_Name,
11951 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011952 "Old_Value"=>$Member_Name,
11953 "New_Value"=>$RenamedTo );
11954 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011955 }
11956 elsif($Type1_Pure{"Type"} eq "Enum")
11957 {
11958 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11959 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11960 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011961 "Old_Value"=>$Member_Name,
11962 "New_Value"=>$RenamedTo );
11963 }
11964 }
11965 elsif($RemovedField{$Member_Pos})
11966 { # removed
11967 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11968 {
11969 my $ProblemType = "Removed_Field";
11970 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011971 or isUnnamed($Member_Name))
11972 {
11973 if($Level eq "Source") {
11974 next;
11975 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011976 $ProblemType = "Removed_Private_Field";
11977 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011978 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011979 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011980 {
11981 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11982 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011983 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 +040011984 { # changed offset
11985 $ProblemType .= "_And_Layout";
11986 }
11987 }
11988 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11989 { # affected size
11990 $ProblemType .= "_And_Size";
11991 }
11992 }
11993 if($ProblemType eq "Removed_Private_Field") {
11994 next;
11995 }
11996 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11997 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011998 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011999 }
12000 elsif($Type2_Pure{"Type"} eq "Union")
12001 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012002 if($Level eq "Binary"
12003 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012004 {
12005 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
12006 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012007 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012008 }
12009 else
12010 {
12011 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
12012 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012013 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012014 }
12015 }
12016 elsif($Type1_Pure{"Type"} eq "Enum")
12017 {
12018 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
12019 "Target"=>$Member_Name,
12020 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012021 "Old_Value"=>$Member_Name );
12022 }
12023 }
12024 else
12025 { # changed
12026 my $MemberPair_Pos = $RelatedField{$Member_Pos};
12027 if($Type1_Pure{"Type"} eq "Enum")
12028 {
12029 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
12030 next if($Member_Value1 eq "");
12031 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
12032 next if($Member_Value2 eq "");
12033 if($Member_Value1 ne $Member_Value2)
12034 {
12035 my $ProblemType = "Enum_Member_Value";
12036 if(isLastElem($Member_Pos, \%Type1_Pure)) {
12037 $ProblemType = "Enum_Last_Member_Value";
12038 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012039 if($SkipConstants{1}{$Member_Name}) {
12040 $ProblemType = "Enum_Private_Member_Value";
12041 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012042 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12043 "Target"=>$Member_Name,
12044 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012045 "Old_Value"=>$Member_Value1,
12046 "New_Value"=>$Member_Value2 );
12047 }
12048 }
12049 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
12050 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012051 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
12052 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
12053
12054 if($Access1 ne "private"
12055 and $Access2 eq "private")
12056 {
12057 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12058 "Target"=>$Member_Name,
12059 "Type_Name"=>$Type1_Pure{"Name"});
12060 }
12061 elsif($Access1 ne "protected"
12062 and $Access1 ne "private"
12063 and $Access2 eq "protected")
12064 {
12065 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12066 "Target"=>$Member_Name,
12067 "Type_Name"=>$Type1_Pure{"Name"});
12068 }
12069
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012070 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12071 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012072 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012073 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12074 $SizeV1 = $BSize1;
12075 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012076 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012077 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12078 $SizeV2 = $BSize2;
12079 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012080 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12081 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012082 if($Level eq "Binary"
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012083 and $SizeV1 and $SizeV2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012084 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012085 {
12086 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12087 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12088 { # field size change (including anon-structures and unions)
12089 # - same types
12090 # - unnamed types
12091 # - bitfields
12092 my $ProblemType = "Field_Size";
12093 if(not isPublic(\%Type1_Pure, $Member_Pos)
12094 or isUnnamed($Member_Name))
12095 { # should not be accessed by applications, goes to "Low Severity"
12096 # example: "abidata" members in GStreamer types
12097 $ProblemType = "Private_".$ProblemType;
12098 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012099 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 +040012100 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012101 if($Type2_Pure{"Type"} ne "Union"
12102 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012103 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012104 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 +040012105 { # changed offset
12106 $ProblemType .= "_And_Layout";
12107 }
12108 }
12109 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12110 $ProblemType .= "_And_Type_Size";
12111 }
12112 }
12113 if($ProblemType eq "Private_Field_Size")
12114 { # private field size with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012115 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012116 if($ProblemType eq "Field_Size")
12117 {
12118 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12119 { # Low severity
12120 $ProblemType = "Struct_Field_Size_Increased";
12121 }
12122 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012123 if($ProblemType)
12124 { # register a problem
12125 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12126 "Target"=>$Member_Name,
12127 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012128 "Old_Size"=>$SizeV1,
12129 "New_Size"=>$SizeV2);
12130 }
12131 }
12132 }
12133 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12134 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12135 { # do NOT check bitfield type changes
12136 next;
12137 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012138 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012139 {
12140 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12141 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12142 {
12143 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12144 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012145 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012146 }
12147 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12148 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12149 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012150 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012151 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012152 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012153 }
12154 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012155 my %Sub_SubChanges = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
12156 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012157 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012158 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12159 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012160
12161 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012162 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012163 or $ProblemType eq "Field_Type_And_Size"
12164 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012165 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012166 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012167 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012168 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012169 %{$Sub_SubChanges{"Field_Became_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012170 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012171 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012172 %{$Sub_SubChanges{"Field_Became_Non_Volatile"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012173 }
12174 }
12175 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12176 {
12177 if($RA==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012178 %{$Sub_SubChanges{"Field_Added_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012179 }
12180 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012181 %{$Sub_SubChanges{"Field_Became_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012182 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012183 }
12184 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12185 {
12186 if($RR==2) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012187 %{$Sub_SubChanges{"Field_Removed_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012188 }
12189 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012190 %{$Sub_SubChanges{"Field_Became_Non_Const"}} = %{$Sub_SubChanges{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012191 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012192 }
12193 }
12194 }
12195
12196 if($Level eq "Source")
12197 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012198 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012199 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012200 my $Old_Value = $Sub_SubChanges{$ProblemType}{"Old_Value"};
12201 my $New_Value = $Sub_SubChanges{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012202
12203 if($ProblemType eq "Field_Type")
12204 {
12205 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012206 delete($Sub_SubChanges{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012207 }
12208 }
12209 }
12210 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012211
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012212 foreach my $ProblemType (keys(%Sub_SubChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012213 {
12214 my $ProblemType_Init = $ProblemType;
12215 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012216 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012217 if(not isPublic(\%Type1_Pure, $Member_Pos)
12218 or isUnnamed($Member_Name)) {
12219 $ProblemType = "Private_".$ProblemType;
12220 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012221 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 +040012222 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012223 if($Type2_Pure{"Type"} ne "Union"
12224 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012225 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012226 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 +040012227 { # changed offset
12228 $ProblemType .= "_And_Layout";
12229 }
12230 }
12231 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12232 $ProblemType .= "_And_Type_Size";
12233 }
12234 }
12235 }
12236 else
12237 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012238 # TODO: Private_Field_Type rule?
12239
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012240 if(not isPublic(\%Type1_Pure, $Member_Pos)
12241 or isUnnamed($Member_Name)) {
12242 next;
12243 }
12244 }
12245 if($ProblemType eq "Private_Field_Type_And_Size")
12246 { # private field change with no effect
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012247 }
12248 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12249 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012250 "Type_Name"=>$Type1_Pure{"Name"});
12251
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012252 foreach my $Attr (keys(%{$Sub_SubChanges{$ProblemType_Init}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012253 { # other properties
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012254 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubChanges{$ProblemType_Init}{$Attr};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012255 }
12256 }
12257 if(not isPublic(\%Type1_Pure, $Member_Pos))
12258 { # do NOT check internal type changes
12259 next;
12260 }
12261 if($MemberType1_Id and $MemberType2_Id)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012262 { # checking member type changes
12263 my $Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
12264
12265 my %DupProblems = ();
12266
12267 foreach my $Sub_SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012268 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012269 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems->{$Sub_SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012270 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012271 if(not defined $AllAffected)
12272 {
12273 if(defined $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}}) {
12274 next;
12275 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012276 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012277
12278 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12279 $SubProblems{$Sub_SubProblemType}{$NewLocation} = $Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation};
12280
12281 if(not defined $AllAffected)
12282 {
12283 $DupProblems{$Sub_SubProblems->{$Sub_SubProblemType}{$Sub_SubLocation}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012284 }
12285 }
12286 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012287
12288 %DupProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012289 }
12290 }
12291 }
12292 }
12293 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12294 { # checking added members, public and private
12295 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12296 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012297 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012298 if($AddedField{$Member_Pos})
12299 { # added
12300 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12301 {
12302 my $ProblemType = "Added_Field";
12303 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012304 or isUnnamed($Member_Name))
12305 {
12306 if($Level eq "Source") {
12307 next;
12308 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012309 $ProblemType = "Added_Private_Field";
12310 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012311 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012312 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012313 {
12314 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12315 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012316 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 +040012317 { # changed offset
12318 $ProblemType .= "_And_Layout";
12319 }
12320 }
12321 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12322 $ProblemType .= "_And_Size";
12323 }
12324 }
12325 if($ProblemType eq "Added_Private_Field")
12326 { # skip added private fields
12327 next;
12328 }
12329 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12330 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012331 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012332 }
12333 elsif($Type2_Pure{"Type"} eq "Union")
12334 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012335 if($Level eq "Binary"
12336 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012337 {
12338 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12339 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012340 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012341 }
12342 else
12343 {
12344 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12345 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012346 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012347 }
12348 }
12349 elsif($Type2_Pure{"Type"} eq "Enum")
12350 {
12351 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12352 next if($Member_Value eq "");
12353 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12354 "Target"=>$Member_Name,
12355 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012356 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012357 }
12358 }
12359 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012360
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012361 pop(@RecurTypes);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040012362 return ($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id} = \%SubProblems);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012363}
12364
12365sub isUnnamed($) {
12366 return $_[0]=~/\Aunnamed\d+\Z/;
12367}
12368
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012369sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012370{
12371 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012372 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12373 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12374 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12375 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012376 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012377 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012378 }
12379 return $TypeName;
12380}
12381
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012382sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012383{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012384 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012385 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012386 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12387 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012388 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012389 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12390 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012391 return () if(not $Type{"Type"});
12392 if($Type{"Type"} ne $Type_Type)
12393 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012394 return () if(not $Type{"BaseType"});
12395 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012396 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012397 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012398 return %Type;
12399}
12400
12401my %TypeSpecAttributes = (
12402 "Const" => 1,
12403 "Volatile" => 1,
12404 "ConstVolatile" => 1,
12405 "Restrict" => 1,
12406 "Typedef" => 1
12407);
12408
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012409sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012410{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012411 my ($TypeId, $Info) = @_;
12412 if(not $TypeId or not $Info
12413 or not $Info->{$TypeId}) {
12414 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012415 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012416 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12417 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12418 }
12419 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012420 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012421 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012422 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012423 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012424 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012425 return %Type;
12426}
12427
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012428sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012429{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012430 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012431 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012432 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12433 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012434 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012435 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12436 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012437 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12438 my $PLevel = 0;
12439 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12440 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012441 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012442 return $PLevel if(not $Type{"BaseType"});
12443 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12444 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12445 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012446}
12447
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012448sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012449{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012450 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012451 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012452 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12453 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012454 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012455 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12456 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012457 return %Type if(not $Type{"BaseType"});
12458 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012459 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012460 return %Type;
12461}
12462
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012463sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012464{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012465 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012466 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012467 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12468 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012469 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012470 my $Qual = "";
12471 if($Type{"Type"} eq "Pointer") {
12472 $Qual .= "*";
12473 }
12474 elsif($Type{"Type"} eq "Ref") {
12475 $Qual .= "&";
12476 }
12477 elsif($Type{"Type"} eq "ConstVolatile") {
12478 $Qual .= "const volatile";
12479 }
12480 elsif($Type{"Type"} eq "Const"
12481 or $Type{"Type"} eq "Volatile"
12482 or $Type{"Type"} eq "Restrict") {
12483 $Qual .= lc($Type{"Type"});
12484 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012485 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012486 return $BQual.$Qual;
12487}
12488
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012489sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012490{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012491 my ($TypeId, $Info) = @_;
12492 if(not $TypeId or not $Info
12493 or not $Info->{$TypeId}) {
12494 return ();
12495 }
12496 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012497 return %Type if(not $Type{"BaseType"});
12498 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012499 {
12500 if($Info->{$BTid}) {
12501 return %{$Info->{$BTid}};
12502 }
12503 else { # something is going wrong
12504 return ();
12505 }
12506 }
12507 else {
12508 return %Type;
12509 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012510}
12511
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012512sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012513{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012514 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012515 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012516 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12517 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012518}
12519
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012520sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012521{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012522 my $Symbol = $_[0];
12523 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12524}
12525
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012526sub isInLineInst($$$) {
12527 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12528}
12529
12530sub isTemplateInstance($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012531{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012532 my ($Symbol, $SInfo, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012533 if($CheckObjectsOnly)
12534 {
12535 if($Symbol!~/\A(_Z|\?)/) {
12536 return 0;
12537 }
12538 if(my $Signature = $tr_name{$Symbol})
12539 {
12540 if(index($Signature,">")==-1) {
12541 return 0;
12542 }
12543 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
12544 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012545 if(index($ShortName,"<")!=-1
12546 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012547 return 1;
12548 }
12549 }
12550 }
12551 }
12552 else
12553 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012554 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012555 {
12556 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
12557 {
12558 if(index($ClassName,"<")!=-1) {
12559 return 1;
12560 }
12561 }
12562 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012563 if(my $ShortName = $SInfo->{"ShortName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012564 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012565 if(index($ShortName,"<")!=-1
12566 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012567 return 1;
12568 }
12569 }
12570 }
12571 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012572}
12573
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012574sub isTemplateSpec($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012575{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012576 my ($Symbol, $SInfo, $LibVersion) = @_;
12577 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012578 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012579 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012580 { # class specialization
12581 return 1;
12582 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012583 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012584 { # method specialization
12585 return 1;
12586 }
12587 }
12588 return 0;
12589}
12590
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012591sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012592{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012593 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012594 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012595 { # non-public global data
12596 return 0;
12597 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040012598
12599 if(defined $SkipInternal)
12600 {
12601 return 0 if($Symbol=~/($SkipInternal)/);
12602 }
12603
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012604 if($CheckObjectsOnly) {
12605 return 0 if($Symbol=~/\A(_init|_fini)\Z/);
12606 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012607 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012608 { # support for old ABI dumps in --headers-only mode
12609 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12610 {
12611 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12612 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012613 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012614 if(not $PType or $PType eq "Unknown") {
12615 return 0;
12616 }
12617 }
12618 }
12619 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012620 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012621 {
12622 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012623 if($SkipSymbols{$LibVersion}{$Symbol})
12624 { # user defined symbols to ignore
12625 return 0;
12626 }
12627 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12628 if(not $NameSpace and $ClassId)
12629 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012630 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012631 }
12632 if($NameSpace)
12633 { # user defined namespaces to ignore
12634 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12635 return 0;
12636 }
12637 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12638 { # nested namespaces
12639 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12640 return 0;
12641 }
12642 }
12643 }
12644 if(my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
12645 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012646 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012647 { # --skip-headers or <skip_headers> (not <skip_including>)
12648 if($Skip==1) {
12649 return 0;
12650 }
12651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012652 }
12653 if($SymbolsListPath and not $SymbolsList{$Symbol})
12654 { # user defined symbols
12655 return 0;
12656 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012657 if($SkipSymbolsListPath and $SkipSymbolsList{$Symbol})
12658 { # user defined symbols
12659 return 0;
12660 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012661 if($AppPath and not $SymbolsList_App{$Symbol})
12662 { # user defined symbols (in application)
12663 return 0;
12664 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012665 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12666 { # non-target symbols
12667 return 0;
12668 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012669 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012670 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012671 if($CheckObjectsOnly)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012672 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012673 if(isTemplateInstance($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012674 return 0;
12675 }
12676 }
12677 else
12678 {
12679 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012680 or isInLineInst($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012681 {
12682 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12683 { # inline virtual methods
12684 if($Type=~/InlineVirt/) {
12685 return 1;
12686 }
12687 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12688 if(not $Allocable)
12689 { # check bases
12690 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12691 {
12692 if(not isCopyingClass($DCId, $LibVersion))
12693 { # exists a derived class without default c-tor
12694 $Allocable=1;
12695 last;
12696 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012697 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012698 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012699 if(not $Allocable) {
12700 return 0;
12701 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012702 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012703 else
12704 { # inline non-virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012705 return 0;
12706 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012707 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012708 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012709 }
12710 }
12711 return 1;
12712}
12713
12714sub mergeImpl()
12715{
12716 my $DiffCmd = get_CmdPath("diff");
12717 if(not $DiffCmd) {
12718 exitStatus("Not_Found", "can't find \"diff\"");
12719 }
12720 foreach my $Interface (sort keys(%{$Symbol_Library{1}}))
12721 { # implementation changes
12722 next if($CompleteSignature{1}{$Interface}{"Private"});
12723 next if(not $CompleteSignature{1}{$Interface}{"Header"} and not $CheckObjectsOnly);
12724 next if(not $Symbol_Library{2}{$Interface} and not $Symbol_Library{2}{$SymVer{2}{$Interface}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012725 if(not symbolFilter($Interface, 1, "Affected", "Binary")) {
12726 next;
12727 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012728 my $Impl1 = canonifyImpl($Interface_Impl{1}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012729 next if(not $Impl1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012730 my $Impl2 = canonifyImpl($Interface_Impl{2}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012731 next if(not $Impl2);
12732 if($Impl1 ne $Impl2)
12733 {
12734 writeFile("$TMP_DIR/impl1", $Impl1);
12735 writeFile("$TMP_DIR/impl2", $Impl2);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012736 my $Diff = `$DiffCmd -rNau \"$TMP_DIR/impl1\" \"$TMP_DIR/impl2\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012737 $Diff=~s/(---|\+\+\+).+\n//g;
12738 $Diff=~s/[ ]{3,}/ /g;
12739 $Diff=~s/\n\@\@/\n \n\@\@/g;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012740 unlink("$TMP_DIR/impl1");
12741 unlink("$TMP_DIR/impl2");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040012742 %{$CompatProblems_Impl{$Interface}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012743 "Diff" => get_CodeView($Diff) );
12744 }
12745 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012746
12747 # clean memory
12748 %Interface_Impl = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012749}
12750
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012751sub canonifyImpl($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012752{
12753 my $FuncBody= $_[0];
12754 return "" if(not $FuncBody);
12755 $FuncBody=~s/0x[a-f\d]+/0x?/g;# addr
12756 $FuncBody=~s/((\A|\n)[a-z]+[\t ]+)[a-f\d]+([^x]|\Z)/$1?$3/g;# call, jump
12757 $FuncBody=~s/# [a-f\d]+ /# ? /g;# call, jump
12758 $FuncBody=~s/%([a-z]+[a-f\d]*)/\%reg/g;# registers
12759 while($FuncBody=~s/\nnop[ \t]*(\n|\Z)/$1/g){};# empty op
12760 $FuncBody=~s/<.+?\.cpp.+?>/<name.cpp>/g;
12761 $FuncBody=~s/(\A|\n)[a-f\d]+ </$1? </g;# 5e74 <_ZN...
12762 $FuncBody=~s/\.L\d+/.L/g;
12763 $FuncBody=~s/#(-?)\d+/#$1?/g;# r3, [r3, #120]
12764 $FuncBody=~s/[\n]{2,}/\n/g;
12765 return $FuncBody;
12766}
12767
12768sub get_CodeView($)
12769{
12770 my $Code = $_[0];
12771 my $View = "";
12772 foreach my $Line (split(/\n/, $Code))
12773 {
12774 if($Line=~s/\A(\+|-)/$1 /g)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012775 { # bold line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012776 $View .= "<tr><td><b>".htmlSpecChars($Line)."</b></td></tr>\n";
12777 }
12778 else {
12779 $View .= "<tr><td>".htmlSpecChars($Line)."</td></tr>\n";
12780 }
12781 }
12782 return "<table class='code_view'>$View</table>\n";
12783}
12784
12785sub getImplementations($$)
12786{
12787 my ($LibVersion, $Path) = @_;
12788 return if(not $LibVersion or not -e $Path);
12789 if($OSgroup eq "macos")
12790 {
12791 my $OtoolCmd = get_CmdPath("otool");
12792 if(not $OtoolCmd) {
12793 exitStatus("Not_Found", "can't find \"otool\"");
12794 }
12795 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012796 foreach my $Line (split(/\n/, `$OtoolCmd -tv \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012797 {
12798 if($Line=~/\A\s*_(\w+)\s*:/i) {
12799 $CurInterface = $1;
12800 }
12801 elsif($Line=~/\A\s*[\da-z]+\s+(.+?)\Z/i) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012802 $Interface_Impl{$LibVersion}{$CurInterface} .= $1."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012803 }
12804 }
12805 }
12806 else
12807 {
12808 my $ObjdumpCmd = get_CmdPath("objdump");
12809 if(not $ObjdumpCmd) {
12810 exitStatus("Not_Found", "can't find \"objdump\"");
12811 }
12812 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012813 foreach my $Line (split(/\n/, `$ObjdumpCmd -d \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012814 {
12815 if($Line=~/\A[\da-z]+\s+<(\w+)>/i) {
12816 $CurInterface = $1;
12817 }
12818 else
12819 { # x86: 51fa:(\t)89 e5 (\t)mov %esp,%ebp
12820 # arm: 5020:(\t)e24cb004(\t)sub(\t)fp, ip, #4(\t); 0x4
12821 if($Line=~/\A\s*[a-f\d]+:\s+([a-f\d]+\s+)+([a-z]+\s+.*?)\s*(;.*|)\Z/i) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012822 $Interface_Impl{$LibVersion}{$CurInterface} .= $2."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012823 }
12824 }
12825 }
12826 }
12827}
12828
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012829sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012830{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012831 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012832 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12833 {
12834 if(link_symbol($Symbol, 1, "+Deps"))
12835 { # linker can find a new symbol
12836 # in the old-version library
12837 # So, it's not a new symbol
12838 next;
12839 }
12840 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012841 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012842 next;
12843 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012844 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012845 }
12846}
12847
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012848sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012849{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012850 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012851 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12852 {
12853 if($CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012854 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012855 }
12856 if(link_symbol($Symbol, 2, "+Deps"))
12857 { # linker can find an old symbol
12858 # in the new-version library
12859 next;
12860 }
12861 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012862 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012863 next;
12864 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012865 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012866 }
12867}
12868
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012869sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012870{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012871 my $Level = $_[0];
12872 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012873 { # checking added symbols
12874 next if($CompleteSignature{2}{$Symbol}{"Private"});
12875 next if(not $CompleteSignature{2}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012876 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012877 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012878 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012879 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012880 { # checking removed symbols
12881 next if($CompleteSignature{1}{$Symbol}{"Private"});
12882 next if(not $CompleteSignature{1}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012883 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012884 { # skip v-tables for templates, that should not be imported by applications
12885 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012886 if(my $CName = $VTableClass{$Symbol})
12887 {
12888 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12889 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012890 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012891 next;
12892 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012893 }
12894 }
12895 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012896 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012897 }
12898 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12899 { # symbols for pure virtual methods cannot be called by clients
12900 next;
12901 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012902 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012903 }
12904}
12905
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012906sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012907{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012908 my ($LibVersion, $V) = @_;
12909 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12910 return $Cache{"checkDump"}{$LibVersion}{$V};
12911 }
12912 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012913}
12914
12915sub detectAdded_H($)
12916{
12917 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012918 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12919 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012920 if($Level eq "Source")
12921 { # remove symbol version
12922 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12923 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012924
12925 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12926 { # skip artificial constructors
12927 next;
12928 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012929 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012930 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12931 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012932 next;
12933 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012934 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012935 next;
12936 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012937 if(not defined $CompleteSignature{1}{$Symbol}
12938 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12939 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012940 if($UsedDump{2}{"SrcBin"})
12941 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012942 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012943 { # support for old and different (!) ABI dumps
12944 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12945 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012946 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012947 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012948 {
12949 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12950 {
12951 if($Lang eq "C")
12952 { # support for old ABI dumps: missed extern "C" functions
12953 next;
12954 }
12955 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012956 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012957 else
12958 {
12959 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012960 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012961 next;
12962 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012963 }
12964 }
12965 }
12966 }
12967 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012968 }
12969 }
12970}
12971
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012972sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012973{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012974 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012975 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12976 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012977 if($Level eq "Source")
12978 { # remove symbol version
12979 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12980 $Symbol=$SN;
12981 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012982 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12983 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012984 next;
12985 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012986 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012987 next;
12988 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012989 if(not defined $CompleteSignature{2}{$Symbol}
12990 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012991 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012992 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012993 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012994 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012995 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012996 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12997 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012998 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012999 if($CheckHeadersOnly)
13000 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013001 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
13002 {
13003 if($Lang eq "C")
13004 { # support for old ABI dumps: missed extern "C" functions
13005 next;
13006 }
13007 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013008 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013009 else
13010 {
13011 if(not link_symbol($Symbol, 1, "-Deps"))
13012 { # skip removed inline symbols
13013 next;
13014 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013015 }
13016 }
13017 }
13018 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040013019 if(not checkDump(1, "2.15"))
13020 {
13021 if($Symbol=~/_IT_E\Z/)
13022 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
13023 next;
13024 }
13025 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013026 if(not $CompleteSignature{1}{$Symbol}{"Class"})
13027 {
13028 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
13029 {
13030 if(defined $Constants{2}{$Short})
13031 {
13032 my $Val = $Constants{2}{$Short}{"Value"};
13033 if(defined $Func_ShortName{2}{$Val})
13034 { # old name defined to new
13035 next;
13036 }
13037 }
13038 }
13039
13040 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013041 $RemovedInt{$Level}{$Symbol} = 1;
13042 if($Level eq "Source")
13043 { # search for a source-compatible equivalent
13044 setAlternative($Symbol, $Level);
13045 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013046 }
13047 }
13048}
13049
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013050sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013051{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013052 my $Level = $_[0];
13053 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013054 { # checking added symbols
13055 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013056 next if($CompleteSignature{2}{$Symbol}{"Private"});
13057 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013058 if($Level eq "Binary")
13059 {
13060 if($CompleteSignature{2}{$Symbol}{"InLine"})
13061 {
13062 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
13063 { # skip inline non-virtual functions
13064 next;
13065 }
13066 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013067 }
13068 else
13069 { # Source
13070 if($SourceAlternative_B{$Symbol}) {
13071 next;
13072 }
13073 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013074 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013075 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013076 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013077 { # checking removed symbols
13078 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013079 next if($CompleteSignature{1}{$Symbol}{"Private"});
13080 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013081 if($Level eq "Binary")
13082 {
13083 if($CompleteSignature{1}{$Symbol}{"InLine"})
13084 {
13085 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
13086 { # skip inline non-virtual functions
13087 next;
13088 }
13089 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013090 }
13091 else
13092 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013093 if(my $Alt = $SourceAlternative{$Symbol})
13094 {
13095 if(defined $CompleteSignature{1}{$Alt}
13096 and $CompleteSignature{1}{$Symbol}{"Const"})
13097 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013098 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013099 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{"this"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013100 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013101 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013102 }
13103 else
13104 { # do NOT show removed symbol
13105 next;
13106 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013107 }
13108 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013109 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013110 }
13111}
13112
13113sub addParamNames($)
13114{
13115 my $LibraryVersion = $_[0];
13116 return if(not keys(%AddIntParams));
13117 my $SecondVersion = $LibraryVersion==1?2:1;
13118 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13119 {
13120 next if(not keys(%{$AddIntParams{$Interface}}));
13121 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013122 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013123 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13124 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013125 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013126 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13127 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13128 {
13129 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13130 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13131 }
13132 }
13133 else {
13134 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13135 }
13136 }
13137 }
13138 }
13139}
13140
13141sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013142{ # detect changed typedefs to show
13143 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013144 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13145 {
13146 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013147 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13148 if(not $BName1 or isAnon($BName1)) {
13149 next;
13150 }
13151 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13152 if(not $BName2 or isAnon($BName2)) {
13153 next;
13154 }
13155 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013156 $ChangedTypedef{$Typedef} = 1;
13157 }
13158 }
13159}
13160
13161sub get_symbol_suffix($$)
13162{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013163 my ($Symbol, $Full) = @_;
13164 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013165 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013166 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013167 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013168 if(not $Full) {
13169 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13170 }
13171 return $Suffix;
13172}
13173
13174sub get_symbol_prefix($$)
13175{
13176 my ($Symbol, $LibVersion) = @_;
13177 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13178 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13179 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013180 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013181 }
13182 return $ShortName;
13183}
13184
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013185sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013186{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013187 my $Symbol = $_[0];
13188 my $PSymbol = $Symbol;
13189 if(not defined $CompleteSignature{2}{$PSymbol}
13190 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13191 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13192 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013193 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013194 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013195 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013196 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013197 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13198 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013199 {
13200 if(defined $CompleteSignature{2}{$PSymbol}
13201 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13202 {
13203 $SourceAlternative{$Symbol} = $PSymbol;
13204 $SourceAlternative_B{$PSymbol} = $Symbol;
13205 if(not defined $CompleteSignature{1}{$PSymbol}
13206 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13207 $SourceReplacement{$Symbol} = $PSymbol;
13208 }
13209 }
13210 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013211 }
13212 else
13213 {
13214 foreach my $Sp ("KV", "VK", "K", "V")
13215 {
13216 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13217 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13218 {
13219 if(defined $CompleteSignature{2}{$PSymbol}
13220 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13221 {
13222 $SourceAlternative{$Symbol} = $PSymbol;
13223 $SourceAlternative_B{$PSymbol} = $Symbol;
13224 if(not defined $CompleteSignature{1}{$PSymbol}
13225 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13226 $SourceReplacement{$Symbol} = $PSymbol;
13227 }
13228 }
13229 }
13230 $PSymbol = $Symbol;
13231 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013232 }
13233 }
13234 }
13235 return "";
13236}
13237
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013238sub getSymKind($$)
13239{
13240 my ($Symbol, $LibVersion) = @_;
13241 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13242 {
13243 return "Global_Data";
13244 }
13245 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13246 {
13247 return "Method";
13248 }
13249 return "Function";
13250}
13251
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013252sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013253{
13254 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013255 my %SubProblems = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013256
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013257 mergeBases($Level);
13258
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013259 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013260 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013261 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013262 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013263 next;
13264 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013265 if(defined $CompleteSignature{1}{$Symbol}
13266 and $CompleteSignature{1}{$Symbol}{"Header"})
13267 { # double-check added symbol
13268 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013269 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013270 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013271 next;
13272 }
13273 if($Symbol=~/\A(_Z|\?)/)
13274 { # C++
13275 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13276 }
13277 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13278 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013279 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13280 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013281 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013282 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013283 {
13284 if($TName_Tid{1}{$AffectedClass_Name})
13285 { # class should exist in previous version
13286 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13287 { # old v-table is NOT copied by old applications
13288 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13289 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013290 "Target"=>get_Signature($Symbol, 2),
13291 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013292 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013293 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013294 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013295 }
13296 }
13297 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013298 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13299 { # check all removed exported symbols
13300 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013301 next;
13302 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013303 if(defined $CompleteSignature{2}{$Symbol}
13304 and $CompleteSignature{2}{$Symbol}{"Header"})
13305 { # double-check removed symbol
13306 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013307 }
13308 if($CompleteSignature{1}{$Symbol}{"Private"})
13309 { # skip private methods
13310 next;
13311 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013312 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013313 next;
13314 }
13315 $CheckedSymbols{$Level}{$Symbol} = 1;
13316 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13317 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013318 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13319 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013320 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013321 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13322 {
13323 if($TName_Tid{2}{$AffectedClass_Name})
13324 { # class should exist in newer version
13325 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13326 { # old v-table is NOT copied by old applications
13327 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13328 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013329 "Target"=>get_Signature($OverriddenMethod, 1),
13330 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013331 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013332 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013333 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013334 }
13335 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013336 if($Level eq "Binary"
13337 and $OSgroup eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013338 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013339 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013340 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013341 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013342 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013343 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013344 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013345 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013346 {
13347 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13348 "Target"=>$tr_name{$Symbol},
13349 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013350 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013351 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013352 else
13353 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013354 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013355 "Target"=>$tr_name{$Symbol},
13356 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013357 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013358 }
13359 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013360 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013361 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013362 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013363 {
13364 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13365 "Target"=>$tr_name{$Symbol},
13366 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013367 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013368 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013369 else
13370 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013371 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013372 "Target"=>$tr_name{$Symbol},
13373 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013374 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013375 }
13376 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013377 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13378 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13379 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13380 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13381 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013382 {
13383 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013384 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013385 $ProblemType = "Global_Data_Symbol_Changed_Type";
13386 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013387 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13388 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013389 "Old_Type"=>$RTName1,
13390 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013391 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013392 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013393 }
13394 }
13395 }
13396 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013397 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013398 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013399 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013400 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013401 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013402 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013403 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013404 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13405 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013406 if($Symbol=~/(C[1-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013407 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013408 my $CtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013409 $NewSym=~s/(C[1-2][EI])/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013410 }
13411 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013412 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13413 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013414 if($Symbol=~/(D[0-2][EI])/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013415 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013416 my $DtorType = $1;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013417 $NewSym=~s/(D[0-2][EI])/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013418 }
13419 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013420 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013421 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013422 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013423 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013424 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013425 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013426 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013427 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013428 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013429 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013430 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013431 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013432 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013433 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013434 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013435 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013436 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013437 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013438 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013439 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013440 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013441 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013442 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013443 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013444 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013445 { # "volatile" to non-"volatile"
13446
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013447 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013448 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013449 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013450 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013451 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013452 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013453 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013454 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013455 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013456 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013457 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013458 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013459 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013460 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013461 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013462 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013463 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013464 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13465 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013466 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013467 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013468 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013469 }
13470 }
13471 }
13472 }
13473 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013474 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13475 { # checking symbols
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013476 $CurrentSymbol = $Symbol;
13477
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013478 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13479 if($Level eq "Source")
13480 { # remove symbol version
13481 $Symbol=$SN;
13482 }
13483 else
13484 { # Binary
13485 if(not $SV)
13486 { # symbol without version
13487 if(my $VSym = $SymVer{1}{$Symbol})
13488 { # the symbol is linked with versioned symbol
13489 if($CompleteSignature{2}{$VSym}{"MnglName"})
13490 { # show report for symbol@ver only
13491 next;
13492 }
13493 elsif(not link_symbol($VSym, 2, "-Deps"))
13494 { # changed version: sym@v1 to sym@v2
13495 # do NOT show report for symbol
13496 next;
13497 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013498 }
13499 }
13500 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013501 my $PSymbol = $Symbol;
13502 if($Level eq "Source"
13503 and my $S = $SourceReplacement{$Symbol})
13504 { # take a source-compatible replacement function
13505 $PSymbol = $S;
13506 }
13507 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013508 { # private symbols
13509 next;
13510 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013511 if(not defined $CompleteSignature{1}{$Symbol}
13512 or not defined $CompleteSignature{2}{$PSymbol})
13513 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013514 next;
13515 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013516 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13517 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13518 { # no mangled name
13519 next;
13520 }
13521 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13522 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013523 { # without a header
13524 next;
13525 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013526
13527 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13528 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13529 { # became pure
13530 next;
13531 }
13532 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13533 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13534 { # became non-pure
13535 next;
13536 }
13537
13538 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13539 { # exported, target, inline virtual and pure virtual
13540 next;
13541 }
13542 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13543 { # exported, target, inline virtual and pure virtual
13544 next;
13545 }
13546
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013547 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013548 {
13549 if($CompleteSignature{1}{$Symbol}{"Data"}
13550 and $CompleteSignature{2}{$PSymbol}{"Data"})
13551 {
13552 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13553 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13554 if(defined $Value1)
13555 {
13556 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13557 if(defined $Value2)
13558 {
13559 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13560 if($Value1 ne $Value2)
13561 {
13562 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13563 "Old_Value"=>$Value1,
13564 "New_Value"=>$Value2,
13565 "Target"=>get_Signature($Symbol, 1) );
13566 }
13567 }
13568 }
13569 }
13570 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013571
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013572 if($CompleteSignature{2}{$PSymbol}{"Private"})
13573 {
13574 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13575 "Target"=>get_Signature_M($PSymbol, 2) );
13576 }
13577 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13578 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13579 {
13580 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13581 "Target"=>get_Signature_M($PSymbol, 2) );
13582 }
13583 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13584 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13585 {
13586 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13587 "Target"=>get_Signature_M($PSymbol, 2) );
13588 }
13589
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013590 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013591 mergeVirtualTables($Symbol, $Level);
13592
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013593 if($COMPILE_ERRORS)
13594 { # if some errors occurred at the compiling stage
13595 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013596 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013597 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013598 { # missed information about parameters in newer version
13599 next;
13600 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013601 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013602 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013603 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013604 next;
13605 }
13606 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013607 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013608 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013609 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013610 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13611 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013612 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13613 "Target"=>get_Signature($Symbol, 1)
13614 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013615 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013616 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013617 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13618 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013619 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013620 "Target"=>get_Signature($Symbol, 1)
13621 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013622 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013623 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13624 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013625 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013626 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013627 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013628 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13629 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13630 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013631 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013632 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013633 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13634 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013635 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013636 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013637 my $ProblemType = "Virtual_Method_Position";
13638 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13639 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013640 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013641 if(isUsedClass($Class_Id, 1, $Level))
13642 {
13643 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013644 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013645 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013646 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13647 next;
13648 }
13649 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013650 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013651 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13652 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013653 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013654 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013655 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013656 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013657 }
13658 }
13659 }
13660 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013661 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13662 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013663 { # do NOT check type changes in pure virtuals
13664 next;
13665 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013666 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013667 if($Symbol=~/\A(_Z|\?)/
13668 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013669 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013670 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013671 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013672 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013673 }
13674 }
13675 else
13676 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013677 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013678 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013679 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013680 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13681 last if($PType2_Name eq "...");
13682 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13683 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013684 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013685 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013686 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013687 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13688 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013689 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13690 $ParamPos_Prev = "lost";
13691 }
13692 }
13693 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013694 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013695 }
13696 if($ParamPos_Prev eq "lost")
13697 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013698 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013699 {
13700 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013701 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013702 $ProblemType = "Added_Unnamed_Parameter";
13703 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013704 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013705 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013706 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013707 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013708 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013709 }
13710 else
13711 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013712 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013713 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013714 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013715 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13716 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013717 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013718 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013719 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013720 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013721 "Target"=>$PName_Old,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013722 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013723 "Param_Type"=>$PType2_Name,
13724 "Old_Value"=>$PName_Old,
13725 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013726 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013727 }
13728 }
13729 else
13730 {
13731 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013732 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013733 $ProblemType = "Added_Middle_Unnamed_Parameter";
13734 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013735 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013736 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013737 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013738 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013739 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013740 }
13741 }
13742 }
13743 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013744 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013745 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013746 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013747 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013748 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013749 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013750 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013751 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013752 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013753 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13754 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013755 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013756 }
13757 }
13758 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013759 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013760 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013761 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013762 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13763 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013764 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13765 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013766 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013767 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013768 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013769 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13770 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013771 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13772 $ParamPos_New = "lost";
13773 }
13774 }
13775 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013776 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013777 }
13778 if($ParamPos_New eq "lost")
13779 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013780 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013781 {
13782 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013783 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013784 $ProblemType = "Removed_Unnamed_Parameter";
13785 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013786 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013787 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013788 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013789 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013790 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013791 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013792 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013793 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013794 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013795 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013796 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013797 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013798 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013799 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013800 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013801 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013802 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013803 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013804 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013805 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013806 "Old_Value"=>$PName,
13807 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013808 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013809 }
13810 }
13811 else
13812 {
13813 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013814 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013815 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13816 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013817 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013818 "Target"=>$PName,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013819 "Param_Pos"=>adjustParamPos($ParamPos, $Symbol, 2),
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013820 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013821 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013822 }
13823 }
13824 }
13825 }
13826 }
13827 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013828 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13829 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013830 my %RC_SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013831
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013832 foreach my $SubProblemType (keys(%RC_SubProblems))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013833 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013834 my $New_Value = $RC_SubProblems{$SubProblemType}{"New_Value"};
13835 my $Old_Value = $RC_SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013836 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013837
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013838 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013839 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013840 if($SubProblemType eq "Return_Type_And_Size") {
13841 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13842 }
13843 elsif($SubProblemType eq "Return_Type_Format") {
13844 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13845 }
13846 else {
13847 $ProblemTypes{"Global_Data_Type"} = 1;
13848 }
13849
13850 # quals
13851 if($SubProblemType eq "Return_Type"
13852 or $SubProblemType eq "Return_Type_And_Size"
13853 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013854 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013855 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13856 { # const to non-const
13857 if($RR==2) {
13858 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13859 }
13860 else {
13861 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13862 }
13863 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013864 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013865 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13866 { # non-const to const
13867 if($RA==2) {
13868 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13869 }
13870 else {
13871 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13872 }
13873 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013874 }
13875 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013876 }
13877 else
13878 {
13879 # quals
13880 if($SubProblemType eq "Return_Type"
13881 or $SubProblemType eq "Return_Type_And_Size"
13882 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013883 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013884 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013885 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013886 if(addedQual($Old_Value, $New_Value, "volatile"))
13887 {
13888 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13889 if($Level ne "Source"
13890 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13891 $ProblemTypes{"Return_Type"} = 1;
13892 }
13893 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013894 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013895 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13896 {
13897 if($RA==2) {
13898 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13899 }
13900 else {
13901 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13902 }
13903 if($Level ne "Source"
13904 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13905 $ProblemTypes{"Return_Type"} = 1;
13906 }
13907 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013908 }
13909 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013910 if($Level eq "Binary"
13911 and not $CompleteSignature{1}{$Symbol}{"Data"})
13912 {
13913 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13914 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13915 { # if one of the architectures is unknown
13916 # then set other arhitecture to unknown too
13917 ($Arch1, $Arch2) = ("unknown", "unknown");
13918 }
13919 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013920 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013921 {
13922 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13923 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13924 }
13925 else
13926 {
13927 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13928 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13929 }
13930
13931 if($SubProblemType eq "Return_Type_Became_Void")
13932 {
13933 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13934 { # parameters stack has been affected
13935 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013936 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013937 }
13938 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013939 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013940 }
13941 }
13942 }
13943 elsif($SubProblemType eq "Return_Type_From_Void")
13944 {
13945 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13946 { # parameters stack has been affected
13947 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013948 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013949 }
13950 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013951 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013952 }
13953 }
13954 }
13955 elsif($SubProblemType eq "Return_Type"
13956 or $SubProblemType eq "Return_Type_And_Size"
13957 or $SubProblemType eq "Return_Type_Format")
13958 {
13959 if($Conv1{"Method"} ne $Conv2{"Method"})
13960 {
13961 if($Conv1{"Method"} eq "stack")
13962 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013963 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013964 }
13965 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013966 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013967 }
13968 }
13969 else
13970 {
13971 if($Conv1{"Method"} eq "reg")
13972 {
13973 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13974 {
13975 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013976 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013977 }
13978 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013979 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013980 }
13981 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013982 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013983 }
13984 }
13985 }
13986 }
13987 }
13988 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013989
13990 if(not keys(%ProblemTypes))
13991 { # default
13992 $ProblemTypes{$SubProblemType} = 1;
13993 }
13994
13995 foreach my $ProblemType (keys(%ProblemTypes))
13996 { # additional
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040013997 $CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"} = $RC_SubProblems{$SubProblemType};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013998 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013999 }
14000 if($ReturnType1_Id and $ReturnType2_Id)
14001 {
14002 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014003 my $Sub_SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
14004
14005 my $AddProblems = {};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014006
14007 if($CompleteSignature{1}{$Symbol}{"Data"})
14008 {
14009 if($Level eq "Binary")
14010 {
14011 if(get_PLevel($ReturnType1_Id, 1)==0)
14012 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014013 if(defined $Sub_SubProblems->{"DataType_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014014 { # add "Global_Data_Size" problem
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014015
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014016 foreach my $Loc (keys(%{$Sub_SubProblems->{"DataType_Size"}}))
14017 {
14018 if(index($Loc,"->")==-1)
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040014019 {
14020 if($Loc eq $Sub_SubProblems->{"DataType_Size"}{$Loc}{"Type_Name"})
14021 {
14022 $AddProblems->{"Global_Data_Size"}{$Loc} = $Sub_SubProblems->{"DataType_Size"}{$Loc}; # add a new problem
14023 last;
14024 }
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014025 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014026 }
14027 }
14028 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014029 if(not defined $AddProblems->{"Global_Data_Size"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014030 {
14031 if(defined $GlobalDataObject{1}{$Symbol}
14032 and defined $GlobalDataObject{2}{$Symbol})
14033 {
14034 my $Old_Size = $GlobalDataObject{1}{$Symbol};
14035 my $New_Size = $GlobalDataObject{2}{$Symbol};
14036 if($Old_Size!=$New_Size)
14037 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014038 $AddProblems->{"Global_Data_Size"}{"retval"} = {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014039 "Old_Size"=>$Old_Size*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014040 "New_Size"=>$New_Size*$BYTE_SIZE };
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014041 }
14042 }
14043 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014044 }
14045 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014046
14047 foreach my $SubProblemType (keys(%{$AddProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014048 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014049 foreach my $SubLocation (keys(%{$AddProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014050 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014051 my $NewLocation = "retval";
14052 if($SubLocation and $SubLocation ne "retval") {
14053 $NewLocation = "retval->".$SubLocation;
14054 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014055 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $AddProblems->{$SubProblemType}{$SubLocation};
14056 }
14057 }
14058
14059 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
14060 {
14061 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
14062 {
Andrey Ponomarenko33ca7f12013-10-03 18:16:26 +040014063 my $NewLocation = "retval";
14064 if($SubLocation and $SubLocation ne "retval") {
14065 $NewLocation = "retval->".$SubLocation;
14066 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014067 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014068 }
14069 }
14070 }
14071
14072 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014073 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
14074 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
14075 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014076 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014077 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014078 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
14079 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014080 if($ThisPtr1_Id and $ThisPtr2_Id)
14081 {
14082 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014083 my $Sub_SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
14084 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014085 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014086 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014087 {
14088 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014089 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014090 }
14091 }
14092 }
14093 }
14094 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014095 if($Level eq "Binary") {
14096 mergeVTables($Level);
14097 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014098 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14099 $CheckedSymbols{$Level}{$Symbol} = 1;
14100 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014101}
14102
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014103sub rmQuals($$)
14104{
14105 my ($Value, $Qual) = @_;
14106 if(not $Qual) {
14107 return $Value;
14108 }
14109 if($Qual eq "all")
14110 { # all quals
14111 $Qual = "const|volatile|restrict";
14112 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014113 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014114 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014115 }
14116 return $Value;
14117}
14118
14119sub cmpBTypes($$$$)
14120{
14121 my ($T1, $T2, $V1, $V2) = @_;
14122 $T1 = uncover_typedefs($T1, $V1);
14123 $T2 = uncover_typedefs($T2, $V2);
14124 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14125}
14126
14127sub addedQual($$$)
14128{
14129 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014130 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014131}
14132
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014133sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014134{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014135 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014136 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014137}
14138
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014139sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014140{
14141 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14142 $Old_Value = uncover_typedefs($Old_Value, $V1);
14143 $New_Value = uncover_typedefs($New_Value, $V2);
14144 if($Old_Value eq $New_Value)
14145 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014146 return 0;
14147 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014148 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014149 { # without a qual
14150 return 0;
14151 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014152 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014153 { # became non-qual
14154 return 1;
14155 }
14156 else
14157 {
14158 my @BQ1 = getQualModel($Old_Value, $Qual);
14159 my @BQ2 = getQualModel($New_Value, $Qual);
14160 foreach (0 .. $#BQ1)
14161 { # removed qual
14162 if($BQ1[$_]==1
14163 and $BQ2[$_]!=1)
14164 {
14165 return 2;
14166 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014167 }
14168 }
14169 return 0;
14170}
14171
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014172sub getQualModel($$)
14173{
14174 my ($Value, $Qual) = @_;
14175 if(not $Qual) {
14176 return $Value;
14177 }
14178
14179 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014180 while($Value=~/(\w+)/ and $1 ne $Qual) {
14181 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014182 }
14183 $Value=~s/[^\*\&\w]+//g;
14184
14185 # modeling
14186 # int*const*const == 011
14187 # int**const == 001
14188 my @Model = ();
14189 my @Elems = split(/[\*\&]/, $Value);
14190 if(not @Elems) {
14191 return (0);
14192 }
14193 foreach (@Elems)
14194 {
14195 if($_ eq $Qual) {
14196 push(@Model, 1);
14197 }
14198 else {
14199 push(@Model, 0);
14200 }
14201 }
14202
14203 return @Model;
14204}
14205
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014206my %StringTypes = map {$_=>1} (
14207 "char*",
14208 "char const*"
14209);
14210
14211my %CharTypes = map {$_=>1} (
14212 "char",
14213 "char const"
14214);
14215
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014216sub showVal($$$)
14217{
14218 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014219 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014220 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014221 if(substr($Value, 0, 2) eq "_Z")
14222 {
14223 if(my $Unmangled = $tr_name{$Value}) {
14224 return $Unmangled;
14225 }
14226 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014227 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014228 { # strings
14229 return "\"$Value\"";
14230 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014231 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014232 { # characters
14233 return "\'$Value\'";
14234 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014235 if($Value eq "")
14236 { # other
14237 return "\'\'";
14238 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014239 return $Value;
14240}
14241
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014242sub getRegs($$$)
14243{
14244 my ($LibVersion, $Symbol, $Pos) = @_;
14245
14246 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14247 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014248 my %Regs = ();
14249 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14250 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014251 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014252 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14253 }
14254 }
14255
14256 return join(", ", sort keys(%Regs));
14257 }
14258
14259 return undef;
14260}
14261
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014262sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014263{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014264 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014265 if(not $Symbol) {
14266 return;
14267 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014268 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14269 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14270 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14271 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014272 if(not $PType1_Id
14273 or not $PType2_Id) {
14274 return;
14275 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014276
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014277 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014278 { # do not merge "this"
14279 if($PName1 eq "this" or $PName2 eq "this") {
14280 return;
14281 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014282 }
14283
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014284 my %Type1 = get_Type($PType1_Id, 1);
14285 my %Type2 = get_Type($PType2_Id, 2);
14286 my %BaseType1 = get_BaseType($PType1_Id, 1);
14287 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014288 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014289
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014290 if($Level eq "Binary")
14291 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014292 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014293 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14294 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14295 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14296 {
14297 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014298 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014299 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014300 }
14301 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14302 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14303 {
14304 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014305 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014306 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1) );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014307 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014308 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014309
14310 if(defined $UsedDump{1}{"DWARF"}
14311 and defined $UsedDump{2}{"DWARF"})
14312 {
14313 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14314 {
14315 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14316 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
14317 if($Old_Regs and $New_Regs)
14318 {
14319 if($Old_Regs ne $New_Regs)
14320 {
14321 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14322 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014323 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014324 "Old_Value"=>$Old_Regs,
14325 "New_Value"=>$New_Regs );
14326 }
14327 }
14328 elsif($Old_Regs and not $New_Regs)
14329 {
14330 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
14331 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014332 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014333 "Old_Value"=>$Old_Regs );
14334 }
14335 elsif(not $Old_Regs and $New_Regs)
14336 {
14337 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14338 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014339 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014340 "New_Value"=>$New_Regs );
14341 }
14342 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14343 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14344 {
14345 if($Old_Offset ne $New_Offset)
14346 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014347 my $Start1 = $CompleteSignature{1}{$Symbol}{"Param"}{0}{"offset"};
14348 my $Start2 = $CompleteSignature{2}{$Symbol}{"Param"}{0}{"offset"};
14349
14350 $Old_Offset = $Old_Offset - $Start1;
14351 $New_Offset = $New_Offset - $Start2;
14352
14353 if($Old_Offset ne $New_Offset)
14354 {
14355 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14356 "Target"=>$PName1,
14357 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
14358 "Old_Value"=>$Old_Offset,
14359 "New_Value"=>$New_Offset );
14360 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014361 }
14362 }
14363 }
14364 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014365 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014366 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14367 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014368 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014369 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014370 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14371 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014372 if(not checkDump(1, "2.13")
14373 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014374 { # support for old ABI dumps
14375 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014376 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014377 if($Type1{"Name"} eq "bool"
14378 and $Value_Old eq "false" and $Value_New eq "0")
14379 { # int class::method ( bool p = 0 );
14380 # old ABI dumps: "false"
14381 # new ABI dumps: "0"
14382 $Value_Old = "0";
14383 }
14384 }
14385 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014386 if(not checkDump(1, "2.18")
14387 and checkDump(2, "2.18"))
14388 { # support for old ABI dumps
14389 if(not defined $Value_Old
14390 and substr($Value_New, 0, 2) eq "_Z") {
14391 $Value_Old = $Value_New;
14392 }
14393 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014394 if(defined $Value_Old)
14395 {
14396 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14397 if(defined $Value_New)
14398 {
14399 $Value_New = showVal($Value_New, $PType2_Id, 2);
14400 if($Value_Old ne $Value_New)
14401 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014402 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014403 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014404 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014405 "Old_Value"=>$Value_Old,
14406 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014407 }
14408 }
14409 else
14410 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014411 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014412 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014413 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014414 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014415 }
14416 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014417 elsif(defined $Value_New)
14418 {
14419 $Value_New = showVal($Value_New, $PType2_Id, 2);
14420 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14421 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014422 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014423 "New_Value"=>$Value_New );
14424 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014425 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014426
14427 if($ChkRnmd)
14428 {
14429 if($PName1 and $PName2 and $PName1 ne $PName2
14430 and $PType1_Id!=-1 and $PType2_Id!=-1
14431 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14432 { # except unnamed "..." value list (Id=-1)
14433 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14434 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014435 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014436 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14437 "Old_Value"=>$PName1,
14438 "New_Value"=>$PName2,
14439 "New_Signature"=>get_Signature($Symbol, 2) );
14440 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014441 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014442
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014443 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014444 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014445
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014446 foreach my $SubProblemType (keys(%SubProblems))
14447 { # add new problems, remove false alarms
14448 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14449 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014450
14451 # quals
14452 if($SubProblemType eq "Parameter_Type"
14453 or $SubProblemType eq "Parameter_Type_And_Size"
14454 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014455 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014456 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014457 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014458 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014459 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014460 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014461 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14462 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14463 }
14464 }
14465 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14466 {
14467 if(removedQual($Old_Value, $New_Value, "volatile")) {
14468 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014469 }
14470 }
14471 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14472 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14473 { # int to "int const"
14474 delete($SubProblems{$SubProblemType});
14475 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014476 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014477 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14478 { # "int const" to int
14479 delete($SubProblems{$SubProblemType});
14480 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014481 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14482 { # "const" to non-"const"
14483 if($RR==2) {
14484 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14485 }
14486 else {
14487 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14488 }
14489 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014490 }
14491 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014492
14493 if($Level eq "Source")
14494 {
14495 foreach my $SubProblemType (keys(%SubProblems))
14496 {
14497 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14498 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14499
14500 if($SubProblemType eq "Parameter_Type")
14501 {
14502 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14503 delete($SubProblems{$SubProblemType});
14504 }
14505 }
14506 }
14507 }
14508
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014509 foreach my $SubProblemType (keys(%SubProblems))
14510 { # modify/register problems
14511 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14512 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014513 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14514 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014515
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014516 my $NewProblemType = $SubProblemType;
14517 if($Old_Value eq "..." and $New_Value ne "...")
14518 { # change from "..." to "int"
14519 if($ParamPos1==0)
14520 { # ISO C requires a named argument before "..."
14521 next;
14522 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014523 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014524 }
14525 elsif($New_Value eq "..." and $Old_Value ne "...")
14526 { # change from "int" to "..."
14527 if($ParamPos2==0)
14528 { # ISO C requires a named argument before "..."
14529 next;
14530 }
14531 $NewProblemType = "Parameter_Became_VaList";
14532 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014533 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014534 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014535 {
14536 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014537 if($Arch1 eq "unknown"
14538 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014539 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014540 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014541 ($Arch1, $Arch2) = ("unknown", "unknown");
14542 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014543 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014544 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014545 { # real
14546 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14547 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14548 }
14549 else
14550 { # model
14551 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14552 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14553 }
14554 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014555 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014556 if($Conv1{"Method"} eq "stack")
14557 {
14558 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14559 $NewProblemType = "Parameter_Type_And_Stack";
14560 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014561 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014562 elsif($Conv1{"Method"} eq "reg")
14563 {
14564 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14565 $NewProblemType = "Parameter_Type_And_Register";
14566 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014567 }
14568 }
14569 else
14570 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014571 if($Conv1{"Method"} eq "stack") {
14572 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014573 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014574 elsif($Conv1{"Method"} eq "register") {
14575 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014576 }
14577 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014578 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14579 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014580 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014581 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014582 "Target"=>$PName1,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014583 "Param_Pos"=>adjustParamPos($ParamPos1, $Symbol, 1),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014584 "New_Signature"=>get_Signature($Symbol, 2) );
14585 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014586 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014587
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014588 @RecurTypes = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014589
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014590 # checking type definition changes
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014591 my $Sub_SubProblems = mergeTypes($PType1_Id, $PType2_Id, $Level);
14592 foreach my $SubProblemType (keys(%{$Sub_SubProblems}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014593 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014594 foreach my $SubLocation (keys(%{$Sub_SubProblems->{$SubProblemType}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014595 {
14596 my $NewProblemType = $SubProblemType;
14597 if($SubProblemType eq "DataType_Size")
14598 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014599 if($Type1{"Type"}!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014600 { # stack has been affected
14601 $NewProblemType = "DataType_Size_And_Stack";
14602 }
14603 }
14604 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014605 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation} = $Sub_SubProblems->{$SubProblemType}{$SubLocation};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014606 }
14607 }
14608}
14609
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014610sub find_ParamPair_Pos_byName($$$)
14611{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014612 my ($Name, $Symbol, $LibVersion) = @_;
14613 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014614 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014615 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14616 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014617 {
14618 return $ParamPos;
14619 }
14620 }
14621 return "lost";
14622}
14623
14624sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14625{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014626 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014627 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014628 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014629 {
14630 next if($Order eq "backward" and $ParamPos>$MediumPos);
14631 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014632 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14633 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014634 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014635 push(@Positions, $ParamPos);
14636 }
14637 }
14638 return @Positions;
14639}
14640
14641sub getTypeIdByName($$)
14642{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014643 my ($TypeName, $LibVersion) = @_;
14644 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014645}
14646
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014647sub diffTypes($$$)
14648{
14649 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14650 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14651 }
14652 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14653 { # skip recursive declarations
14654 return 0;
14655 }
14656
14657 pushType($_[0], $_[1], \@RecurTypes_Diff);
14658 my $Diff = diffTypes_I(@_);
14659 pop(@RecurTypes_Diff);
14660
14661 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14662}
14663
14664sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014665{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014666 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014667
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014668 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14669 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014670
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014671 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14672 { # equal types
14673 return 0;
14674 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014675 if($Type1_Pure{"Name"} eq "void")
14676 { # from void* to something
14677 return 0;
14678 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014679 if($Type1_Pure{"Name"}=~/\*/
14680 or $Type2_Pure{"Name"}=~/\*/)
14681 { # compared in detectTypeChange()
14682 return 0;
14683 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014684
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014685 my %FloatType = map {$_=>1} (
14686 "float",
14687 "double",
14688 "long double"
14689 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014690
14691 my $T1 = $Type1_Pure{"Type"};
14692 my $T2 = $Type2_Pure{"Type"};
14693
14694 if($T1 eq "Struct"
14695 and $T2 eq "Class")
14696 { # compare as data structures
14697 $T2 = "Struct";
14698 }
14699
14700 if($T1 eq "Class"
14701 and $T2 eq "Struct")
14702 { # compare as data structures
14703 $T1 = "Struct";
14704 }
14705
14706 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014707 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014708 if($T1 eq "Intrinsic"
14709 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014710 { # "int" to "enum"
14711 return 0;
14712 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014713 elsif($T2 eq "Intrinsic"
14714 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014715 { # "enum" to "int"
14716 return 0;
14717 }
14718 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014719 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014720 # ...
14721 return 1;
14722 }
14723 }
14724 else
14725 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014726 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014727 {
14728 if($FloatType{$Type1_Pure{"Name"}}
14729 or $FloatType{$Type2_Pure{"Name"}})
14730 { # "float" to "double"
14731 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014732 if($Level eq "Source")
14733 { # Safe
14734 return 0;
14735 }
14736 else {
14737 return 1;
14738 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014739 }
14740 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014741 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014742 {
14743 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14744 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014745 if(not @Membs1
14746 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014747 { # private
14748 return 0;
14749 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014750 if($#Membs1!=$#Membs2)
14751 { # different number of elements
14752 return 1;
14753 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014754 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014755 {
14756 foreach my $Pos (@Membs1)
14757 { # compare elements by name and value
14758 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14759 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14760 { # different names
14761 return 1;
14762 }
14763 }
14764 }
14765 else
14766 {
14767 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014768 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014769 if($Level eq "Source")
14770 {
14771 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14772 { # different names
14773 return 1;
14774 }
14775 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014776
14777 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14778 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14779
14780 if($MT1{"Name"} ne $MT2{"Name"}
14781 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14782 {
14783 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14784 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14785
14786 if($PL1 ne $PL2)
14787 { # different pointer level
14788 return 1;
14789 }
14790
14791 # compare base types
14792 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14793 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14794
14795 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14796 { # different types
14797 return 1;
14798 }
14799 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014800 }
14801 }
14802 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014803 else
14804 {
14805 # TODO: arrays, etc.
14806 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014807 }
14808 return 0;
14809}
14810
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014811sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014812{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014813 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014814 if(not $Type1_Id or not $Type2_Id) {
14815 return ();
14816 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014817 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014818 my %Type1 = get_Type($Type1_Id, 1);
14819 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014820 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14821 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14822 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14823 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 +040014824
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014825 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14826 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014827 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14828 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14829 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14830 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14831 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14832 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14833 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014834 if($Type1{"Name"} eq $Type2{"Name"})
14835 {
14836 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14837 { # will be reported in mergeTypes() as typedef problem
14838 return ();
14839 }
14840 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14841 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14842 if(%Typedef_1 and %Typedef_2)
14843 {
14844 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14845 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14846 { # const Typedef
14847 return ();
14848 }
14849 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014850 }
14851 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14852 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014853 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014854 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14855 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014856 {
14857 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14858 "Old_Value"=>$Type1_Base{"Name"},
14859 "New_Value"=>$Type2_Base{"Name"},
14860 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014861 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014862 }
14863 else
14864 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014865 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014866 { # format change
14867 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14868 "Old_Value"=>$Type1_Base{"Name"},
14869 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014870 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014871 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014872 }
14873 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14874 {
14875 %{$LocalProblems{$Prefix."_BaseType"}}=(
14876 "Old_Value"=>$Type1_Base{"Name"},
14877 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014878 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014879 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014880 }
14881 }
14882 }
14883 }
14884 elsif($Type1{"Name"} ne $Type2{"Name"})
14885 { # type change
14886 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14887 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014888 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014889 and $Type1_Pure{"Name"} eq "void")
14890 {
14891 %{$LocalProblems{"Return_Type_From_Void"}}=(
14892 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014893 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014894 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014895 elsif($Prefix eq "Return"
14896 and $Type2_Pure{"Name"} eq "void")
14897 {
14898 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14899 "Old_Value"=>$Type1{"Name"},
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014900 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014901 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014902 else
14903 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014904 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014905 and $Type1{"Size"} and $Type2{"Size"}
14906 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014907 {
14908 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14909 "Old_Value"=>$Type1{"Name"},
14910 "New_Value"=>$Type2{"Name"},
14911 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014912 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014913 }
14914 else
14915 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014916 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014917 { # format change
14918 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14919 "Old_Value"=>$Type1{"Name"},
14920 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014921 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014922 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014923 }
14924 elsif(tNameLock($Type1_Id, $Type2_Id))
14925 { # FIXME: correct this condition
14926 %{$LocalProblems{$Prefix."_Type"}}=(
14927 "Old_Value"=>$Type1{"Name"},
14928 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014929 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040014930 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014931 }
14932 }
14933 }
14934 }
14935 }
14936 if($Type1_PLevel!=$Type2_PLevel)
14937 {
14938 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14939 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14940 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014941 if($Level eq "Source")
14942 {
14943 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014944 "Old_Value"=>$Type1_PLevel,
14945 "New_Value"=>$Type2_PLevel);
14946 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014947 else
14948 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014949 if($Type2_PLevel>$Type1_PLevel)
14950 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014951 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14952 "Old_Value"=>$Type1_PLevel,
14953 "New_Value"=>$Type2_PLevel);
14954 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014955 else
14956 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014957 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14958 "Old_Value"=>$Type1_PLevel,
14959 "New_Value"=>$Type2_PLevel);
14960 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014961 }
14962 }
14963 }
Andrey Ponomarenkoac687f92013-08-01 18:53:30 +040014964 if($Type1_Pure{"Type"} eq "Array"
14965 and $Type1_Pure{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014966 { # base_type[N] -> base_type[N]
14967 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014968 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014969 foreach my $SubProblemType (keys(%SubProblems))
14970 {
14971 $SubProblemType=~s/_Type/_BaseType/g;
14972 next if(defined $LocalProblems{$SubProblemType});
14973 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14974 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14975 }
14976 }
14977 }
14978 return %LocalProblems;
14979}
14980
14981sub tNameLock($$)
14982{
14983 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014984 my $Changed = 0;
14985 if(differentDumps("G"))
14986 { # different GCC versions
14987 $Changed = 1;
14988 }
14989 elsif(differentDumps("V"))
14990 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014991 if(not checkDump(1, "2.20")
14992 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014993 { # latest names update
14994 # 2.6: added restrict qualifier
14995 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014996 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014997 $Changed = 1;
14998 }
14999 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015000
15001 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
15002 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
15003
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015004 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
15005 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
15006
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015007 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015008 { # different formats
15009 if($UseOldDumps)
15010 { # old dumps
15011 return 0;
15012 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015013
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015014 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015015 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015016 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015017 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015018 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015019 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015020 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015021 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015022 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
15023 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
15024 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015025 { # equal base types
15026 return 0;
15027 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015028
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015029 if(not checkDump(1, "2.13")
15030 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015031 { # broken array names in ABI dumps < 2.13
15032 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015033 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015034 return 0;
15035 }
15036 }
15037
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015038 if(not checkDump(1, "2.6")
15039 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015040 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015041 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015042 and $TN2=~/\brestrict\b/) {
15043 return 0;
15044 }
15045 }
15046
15047 if(not checkDump(1, "2.20")
15048 or not checkDump(2, "2.20"))
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015049 { # added type prefix in 2.20
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015050 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
15051 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015052 return 0;
15053 }
15054 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015055 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015056 else
15057 {
15058 # typedef struct {...} type_t
15059 # typedef struct type_t {...} type_t
15060 if(index($TN1, " ".$TN2)!=-1)
15061 {
15062 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
15063 return 0;
15064 }
15065 }
15066 if(index($TN2, " ".$TN1)!=-1)
15067 {
15068 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
15069 return 0;
15070 }
15071 }
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040015072
15073 if($TT1 eq "FuncPtr"
15074 and $TT2 eq "FuncPtr")
15075 {
15076 my $TN1_C = $TN1;
15077 my $TN2_C = $TN2;
15078
15079 $TN1_C=~s/\b(struct|union) //g;
15080 $TN2_C=~s/\b(struct|union) //g;
15081
15082 if($TN1_C eq $TN2_C) {
15083 return 0;
15084 }
15085 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015086 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015087
15088 my ($N1, $N2) = ($TN1, $TN2);
15089 $N1=~s/\b(struct|union) //g;
15090 $N2=~s/\b(struct|union) //g;
15091
15092 if($N1 eq $N2)
15093 { # QList<struct QUrl> and QList<QUrl>
15094 return 0;
15095 }
15096
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015097 return 1;
15098}
15099
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015100sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015101{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015102 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015103 if(defined $Cache{"differentDumps"}{$Check}) {
15104 return $Cache{"differentDumps"}{$Check};
15105 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015106 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015107 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015108 if($Check eq "G")
15109 {
15110 if(getGccVersion(1) ne getGccVersion(2))
15111 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015112 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015113 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015114 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015115 if($Check eq "V")
15116 {
15117 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15118 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15119 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015120 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015121 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015122 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015123 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015124 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015125}
15126
15127sub formatVersion($$)
15128{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015129 my ($V, $Digits) = @_;
15130 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015131 return join(".", splice(@Elems, 0, $Digits));
15132}
15133
15134sub htmlSpecChars($)
15135{
15136 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015137 if(not $Str) {
15138 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015139 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015140 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15141 $Str=~s/</&lt;/g;
15142 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15143 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015144 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15145 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015146 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015147 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015148 $Str=~s/\n/<br\/>/g;
15149 $Str=~s/\"/&quot;/g;
15150 $Str=~s/\'/&#39;/g;
15151 return $Str;
15152}
15153
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015154sub xmlSpecChars($)
15155{
15156 my $Str = $_[0];
15157 if(not $Str) {
15158 return $Str;
15159 }
15160
15161 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15162 $Str=~s/</&lt;/g;
15163 $Str=~s/>/&gt;/g;
15164
15165 $Str=~s/\"/&quot;/g;
15166 $Str=~s/\'/&#39;/g;
15167
15168 return $Str;
15169}
15170
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015171sub xmlSpecChars_R($)
15172{
15173 my $Str = $_[0];
15174 if(not $Str) {
15175 return $Str;
15176 }
15177
15178 $Str=~s/&amp;/&/g;
15179 $Str=~s/&lt;/</g;
15180 $Str=~s/&gt;/>/g;
15181
15182 $Str=~s/&quot;/"/g;
15183 $Str=~s/&#39;/'/g;
15184
15185 return $Str;
15186}
15187
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015188sub black_name($)
15189{
15190 my $Name = $_[0];
15191 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15192}
15193
15194sub highLight_Signature($)
15195{
15196 my $Signature = $_[0];
15197 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15198}
15199
15200sub highLight_Signature_Italic_Color($)
15201{
15202 my $Signature = $_[0];
15203 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15204}
15205
15206sub separate_symbol($)
15207{
15208 my $Symbol = $_[0];
15209 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15210 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15211 ($Name, $Spec, $Ver) = ($1, $2, $3);
15212 }
15213 return ($Name, $Spec, $Ver);
15214}
15215
15216sub cut_f_attrs($)
15217{
15218 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15219 return $2;
15220 }
15221 return "";
15222}
15223
15224sub highLight_Signature_PPos_Italic($$$$$)
15225{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015226 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15227 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015228 if($CheckObjectsOnly) {
15229 $ItalicParams=$ColorParams=0;
15230 }
15231 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15232 my $Return = "";
15233 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15234 $Return = $2;
15235 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015236 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015237 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015238 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015239 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015240 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015241 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015242 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015243 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015244 }
15245 return $Signature;
15246 }
15247 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15248 $Begin.=" " if($Begin!~/ \Z/);
15249 $End = cut_f_attrs($Signature);
15250 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015251 my ($Short, $Params) = split_Signature($Signature);
15252 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015253 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015254 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015255 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015256 $Part=~s/\A\s+|\s+\Z//g;
15257 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15258 if($Part=~/\([\*]+(\w+)\)/i) {
15259 $ParamName = $1;#func-ptr
15260 }
15261 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15262 $ParamName = $1;
15263 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015264 if(not $ParamName)
15265 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015266 push(@Parts, $Part_Styled);
15267 next;
15268 }
15269 if($ItalicParams and not $TName_Tid{1}{$Part}
15270 and not $TName_Tid{2}{$Part})
15271 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015272 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015273 if($Param_Pos ne ""
15274 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015275 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015276 }
15277 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015278 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015279 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015280 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015281 }
15282 $Part_Styled=~s/,(\w)/, $1/g;
15283 push(@Parts, $Part_Styled);
15284 }
15285 if(@Parts)
15286 {
15287 foreach my $Num (0 .. $#Parts)
15288 {
15289 if($Num==$#Parts)
15290 { # add ")" to the last parameter
15291 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15292 }
15293 elsif(length($Parts[$Num])<=45) {
15294 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15295 }
15296 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015297 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015298 }
15299 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015300 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015301 }
15302 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015303 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015304 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015305 $Signature=~s!\[\]![&#160;]!g;
15306 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015307 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15308 if($SymbolVersion) {
15309 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15310 }
15311 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015312}
15313
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015314sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015315{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015316 my $Signature = $_[0];
15317 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15318 {
15319 $Signature=~s/\A\Q$ShortName\E\(//g;
15320 cut_f_attrs($Signature);
15321 $Signature=~s/\)\Z//;
15322 return ($ShortName, $Signature);
15323 }
15324
15325 # error
15326 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015327}
15328
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015329sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015330{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015331 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015332 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015333 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15334 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015335 foreach my $Pos (0 .. length($Params) - 1)
15336 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015337 my $S = substr($Params, $Pos, 1);
15338 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015339 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015340 }
15341 if($S eq "," and
15342 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015343 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015344 if($Comma)
15345 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015346 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015347 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015348 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015349 }
15350 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015351 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015352 }
15353 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015354 if(not $Sp)
15355 { # remove spaces
15356 foreach (@Parts)
15357 {
15358 s/\A //g;
15359 s/ \Z//g;
15360 }
15361 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015362 return @Parts;
15363}
15364
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015365sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015366{
15367 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015368 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015369 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015370 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15371 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015372 $Center+=length($1);
15373 }
15374 foreach my $Pos (0 .. length($Sign)-1)
15375 {
15376 my $S = substr($Sign, $Pos, 1);
15377 if($S eq $Target)
15378 {
15379 if($B{"("}==$B{")"}
15380 and $B{"<"}==$B{">"}) {
15381 return $Center;
15382 }
15383 }
15384 if(defined $B{$S}) {
15385 $B{$S}+=1;
15386 }
15387 $Center+=1;
15388 }
15389 return 0;
15390}
15391
15392sub appendFile($$)
15393{
15394 my ($Path, $Content) = @_;
15395 return if(not $Path);
15396 if(my $Dir = get_dirname($Path)) {
15397 mkpath($Dir);
15398 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015399 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015400 print FILE $Content;
15401 close(FILE);
15402}
15403
15404sub writeFile($$)
15405{
15406 my ($Path, $Content) = @_;
15407 return if(not $Path);
15408 if(my $Dir = get_dirname($Path)) {
15409 mkpath($Dir);
15410 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015411 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015412 print FILE $Content;
15413 close(FILE);
15414}
15415
15416sub readFile($)
15417{
15418 my $Path = $_[0];
15419 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015420 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015421 local $/ = undef;
15422 my $Content = <FILE>;
15423 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015424 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015425 $Content=~s/\r/\n/g;
15426 }
15427 return $Content;
15428}
15429
15430sub get_filename($)
15431{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015432 if(defined $Cache{"get_filename"}{$_[0]}) {
15433 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015434 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015435 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15436 return ($Cache{"get_filename"}{$_[0]}=$1);
15437 }
15438 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015439}
15440
15441sub get_dirname($)
15442{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015443 if(defined $Cache{"get_dirname"}{$_[0]}) {
15444 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015445 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015446 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15447 return ($Cache{"get_dirname"}{$_[0]}=$1);
15448 }
15449 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015450}
15451
15452sub separate_path($) {
15453 return (get_dirname($_[0]), get_filename($_[0]));
15454}
15455
15456sub esc($)
15457{
15458 my $Str = $_[0];
15459 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15460 return $Str;
15461}
15462
15463sub readLineNum($$)
15464{
15465 my ($Path, $Num) = @_;
15466 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015467 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015468 foreach (1 ... $Num) {
15469 <FILE>;
15470 }
15471 my $Line = <FILE>;
15472 close(FILE);
15473 return $Line;
15474}
15475
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015476sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015477{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015478 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015479 return () if(not $Path or not -f $Path);
15480 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015481 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15482 {
15483 foreach my $AttrVal (split(/;/, $1))
15484 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015485 if($AttrVal=~/(.+):(.+)/)
15486 {
15487 my ($Name, $Value) = ($1, $2);
15488 $Attributes{$Name} = $Value;
15489 }
15490 }
15491 }
15492 return \%Attributes;
15493}
15494
15495sub is_abs($) {
15496 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15497}
15498
15499sub get_abs_path($)
15500{ # abs_path() should NOT be called for absolute inputs
15501 # because it can change them
15502 my $Path = $_[0];
15503 if(not is_abs($Path)) {
15504 $Path = abs_path($Path);
15505 }
15506 return $Path;
15507}
15508
15509sub get_OSgroup()
15510{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015511 my $N = $Config{"osname"};
15512 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015513 return "macos";
15514 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015515 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015516 return "bsd";
15517 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015518 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015519 return "beos";
15520 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015521 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015522 return "symbian";
15523 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015524 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015525 return "windows";
15526 }
15527 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015528 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015529 }
15530}
15531
15532sub getGccVersion($)
15533{
15534 my $LibVersion = $_[0];
15535 if($GCC_VERSION{$LibVersion})
15536 { # dump version
15537 return $GCC_VERSION{$LibVersion};
15538 }
15539 elsif($UsedDump{$LibVersion}{"V"})
15540 { # old-version dumps
15541 return "unknown";
15542 }
15543 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15544 if(not $GccVersion) {
15545 return "unknown";
15546 }
15547 return $GccVersion;
15548}
15549
15550sub showArch($)
15551{
15552 my $Arch = $_[0];
15553 if($Arch eq "arm"
15554 or $Arch eq "mips") {
15555 return uc($Arch);
15556 }
15557 return $Arch;
15558}
15559
15560sub getArch($)
15561{
15562 my $LibVersion = $_[0];
15563 if($CPU_ARCH{$LibVersion})
15564 { # dump version
15565 return $CPU_ARCH{$LibVersion};
15566 }
15567 elsif($UsedDump{$LibVersion}{"V"})
15568 { # old-version dumps
15569 return "unknown";
15570 }
15571 if(defined $Cache{"getArch"}{$LibVersion}) {
15572 return $Cache{"getArch"}{$LibVersion};
15573 }
15574 my $Arch = get_dumpmachine($GCC_PATH); # host version
15575 if(not $Arch) {
15576 return "unknown";
15577 }
15578 if($Arch=~/\A([\w]{3,})(-|\Z)/) {
15579 $Arch = $1;
15580 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040015581 $Arch = "x86" if($Arch=~/\Ai[3-7]86\Z/i);
15582 $Arch = "x86_64" if($Arch=~/\Aamd64\Z/i);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040015583 if($OSgroup eq "windows")
15584 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015585 $Arch = "x86" if($Arch=~/win32|mingw32/i);
15586 $Arch = "x86_64" if($Arch=~/win64|mingw64/i);
15587 }
15588 $Cache{"getArch"}{$LibVersion} = $Arch;
15589 return $Arch;
15590}
15591
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015592sub get_Report_Header($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015593{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015594 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015595 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015596 if(getArch(1) ne getArch(2)
15597 or getArch(1) eq "unknown"
15598 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015599 { # don't show architecture in the header
15600 $ArchInfo="";
15601 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015602 my $Report_Header = "<h1><span class='nowrap'>";
15603 if($Level eq "Source") {
15604 $Report_Header .= "Source compatibility";
15605 }
15606 elsif($Level eq "Binary") {
15607 $Report_Header .= "Binary compatibility";
15608 }
15609 else {
15610 $Report_Header .= "API compatibility";
15611 }
15612 $Report_Header .= " report for the <span style='color:Blue;'>$TargetLibraryFName</span> $TargetComponent</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015613 $Report_Header .= " <span class='nowrap'>&#160;between <span style='color:Red;'>".$Descriptor{1}{"Version"}."</span> and <span style='color:Red;'>".$Descriptor{2}{"Version"}."</span> versions$ArchInfo</span>";
15614 if($AppPath) {
15615 $Report_Header .= " <span class='nowrap'>&#160;(relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)</span>";
15616 }
15617 $Report_Header .= "</h1>\n";
15618 return $Report_Header;
15619}
15620
15621sub get_SourceInfo()
15622{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015623 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015624 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015625 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015626 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015627 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015628 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15629 $CheckedHeaders .= "<div class='h_list'>\n";
15630 foreach my $Header_Path (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15631 {
15632 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15633 my $Name = get_filename($Identity);
15634 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15635 $CheckedHeaders .= $Name.$Comment."<br/>\n";
15636 }
15637 $CheckedHeaders .= "</div>\n";
15638 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015639 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015640
15641 if(my @Sources = keys(%{$Registered_Sources{1}}))
15642 {
15643 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15644 $CheckedSources .= "<div class='h_list'>\n";
15645 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15646 {
15647 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15648 my $Name = get_filename($Identity);
15649 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15650 $CheckedSources .= $Name.$Comment."<br/>\n";
15651 }
15652 $CheckedSources .= "</div>\n";
15653 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15654 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015655 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015656 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015657 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015658 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015659 $CheckedLibs .= "<div class='lib_list'>\n";
15660 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15661 {
15662 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15663 $CheckedLibs .= $Library."<br/>\n";
15664 }
15665 $CheckedLibs .= "</div>\n";
15666 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015667 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015668 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15669}
15670
15671sub get_ObjTitle()
15672{
15673 if(defined $UsedDump{1}{"DWARF"}) {
15674 return "Objects";
15675 }
15676 else {
15677 return ucfirst($SLIB_TYPE)." Libraries";
15678 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015679}
15680
15681sub get_TypeProblems_Count($$$)
15682{
15683 my ($TypeChanges, $TargetPriority, $Level) = @_;
15684 my $Type_Problems_Count = 0;
15685 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15686 {
15687 my %Kinds_Target = ();
15688 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15689 {
15690 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15691 {
15692 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015693 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
15694 next if($Severity ne $TargetPriority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015695 if($Kinds_Target{$Kind}{$Target}) {
15696 next;
15697 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015698
15699 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target})
15700 {
15701 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
15702 { # select a problem with the highest priority
15703 next;
15704 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015705 }
15706 $Kinds_Target{$Kind}{$Target} = 1;
15707 $Type_Problems_Count += 1;
15708 }
15709 }
15710 }
15711 return $Type_Problems_Count;
15712}
15713
15714sub get_Summary($)
15715{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015716 my $Level = $_[0];
15717 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015718 $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 +040015719 %{$RESULT{$Level}} = (
15720 "Problems"=>0,
15721 "Warnings"=>0,
15722 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015723 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015724 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015725 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015726 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015727 {
15728 if(not defined $CompatRules{$Level}{$Kind})
15729 { # unknown rule
15730 if(not $UnknownRules{$Level}{$Kind})
15731 { # only one warning
15732 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15733 $UnknownRules{$Level}{$Kind}=1;
15734 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015735 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015736 }
15737 }
15738 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015739 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15740 {
15741 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15742 {
15743 if(not defined $CompatRules{$Level}{$Kind})
15744 { # unknown rule
15745 if(not $UnknownRules{$Level}{$Kind})
15746 { # only one warning
15747 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15748 $UnknownRules{$Level}{$Kind}=1;
15749 }
15750 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15751 }
15752 }
15753 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015754 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015755 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015756 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015757 {
15758 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15759 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015760 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015761 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015762 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015763 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015764 $Added += 1;
15765 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015766 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015767 {
15768 $Removed += 1;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015769 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015770 }
15771 else
15772 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015773 if($Severity eq "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015774 $I_Other += 1;
15775 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015776 elsif($Severity eq "High") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015777 $I_Problems_High += 1;
15778 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015779 elsif($Severity eq "Medium") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015780 $I_Problems_Medium += 1;
15781 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015782 elsif($Severity eq "Low") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015783 $I_Problems_Low += 1;
15784 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015785 if(($Severity ne "Low" or $StrictCompat)
15786 and $Severity ne "Safe") {
15787 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015788 }
15789 }
15790 }
15791 }
15792 }
15793 }
15794 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015795 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015796 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015797 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015798 {
15799 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15800 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015801 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015802 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015803 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15804 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015805 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015806 my $MaxSeverity = $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target};
15807
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015808 if($MaxSeverity and $Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015809 { # select a problem with the highest priority
15810 next;
15811 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015812
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015813 if(($Severity ne "Low" or $StrictCompat)
15814 and $Severity ne "Safe")
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015815 {
15816 if(defined $TotalAffected{$Level}{$Interface})
15817 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015818 if($Severity_Val{$Severity}>$Severity_Val{$TotalAffected{$Level}{$Interface}}) {
15819 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015820 }
15821 }
15822 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015823 $TotalAffected{$Level}{$Interface} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015824 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015825 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015826
15827 $TypeChanges{$Type_Name}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
15828
15829 if($MaxSeverity)
15830 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015831 if($Severity_Val{$Severity}>$Severity_Val{$MaxSeverity}) {
15832 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015833 }
15834 }
15835 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040015836 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = $Severity;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015837 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015838 }
15839 }
15840 }
15841 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015842
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015843 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15844 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15845 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15846 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015847
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015848 %TypeChanges = (); # free memory
15849
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015850 if($CheckObjectsOnly)
15851 { # only removed exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015852 $RESULT{$Level}{"Affected"} = $Removed*100/keys(%{$Symbol_Library{1}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015853 }
15854 else
15855 { # changed and removed public symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015856 my $SCount = keys(%{$CheckedSymbols{$Level}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015857 if($ExtendedCheck)
15858 { # don't count external_func_0 for constants
15859 $SCount-=1;
15860 }
15861 if($SCount)
15862 {
15863 my %Weight = (
15864 "High" => 100,
15865 "Medium" => 50,
15866 "Low" => 25
15867 );
15868 foreach (keys(%{$TotalAffected{$Level}})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015869 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015870 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015871 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015872 }
15873 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015874 $RESULT{$Level}{"Affected"} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015875 }
15876 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015877 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15878 if($RESULT{$Level}{"Affected"}>=100) {
15879 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015880 }
15881
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015882 $RESULT{$Level}{"Problems"} += $Removed;
15883 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015884 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015885 if($StrictCompat) {
15886 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15887 }
15888 else {
15889 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15890 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015891
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015892 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015893 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015894 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015895 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040015896 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015897 if($Severity eq "Safe")
15898 {
15899 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015900 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015901 elsif($Severity eq "Low")
15902 {
15903 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015904 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015905 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015906 }
15907
15908 if($C_Problems_Low)
15909 {
15910 if($StrictCompat) {
15911 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15912 }
15913 else {
15914 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015915 }
15916 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015917 if($CheckImpl and $Level eq "Binary")
15918 {
15919 if($StrictCompat) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015920 $RESULT{$Level}{"Problems"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015921 }
15922 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015923 $RESULT{$Level}{"Warnings"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015924 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015925 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015926 if($RESULT{$Level}{"Problems"}
15927 and $RESULT{$Level}{"Affected"}) {
15928 $RESULT{$Level}{"Verdict"} = "incompatible";
15929 }
15930 else {
15931 $RESULT{$Level}{"Verdict"} = "compatible";
15932 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015933
15934 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15935 if(not $TotalTypes)
15936 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015937 $TotalTypes = keys(%{$TName_Tid{1}});
15938 }
15939
15940 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15941 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15942
15943 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15944
15945 if($ReportFormat eq "xml")
15946 { # XML
15947 # test info
15948 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15949 $TestInfo .= " <version1>\n";
15950 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015951 $TestInfo .= " <arch>$Arch1</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015952 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15953 $TestInfo .= " </version1>\n";
15954
15955 $TestInfo .= " <version2>\n";
15956 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040015957 $TestInfo .= " <arch>$Arch2</arch>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015958 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15959 $TestInfo .= " </version2>\n";
15960 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15961
15962 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015963 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015964 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015965 $TestResults .= " <headers>\n";
15966 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15967 {
15968 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15969 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15970 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15971 }
15972 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015973 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015974
15975 if(my @Sources = keys(%{$Registered_Sources{1}}))
15976 {
15977 $TestResults .= " <sources>\n";
15978 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15979 {
15980 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15981 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15982 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15983 }
15984 $TestResults .= " </sources>\n";
15985 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015986
15987 $TestResults .= " <libs>\n";
15988 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15989 {
15990 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15991 $TestResults .= " <name>$Library</name>\n";
15992 }
15993 $TestResults .= " </libs>\n";
15994
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015995 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015996 $TestResults .= " <types>".$TotalTypes."</types>\n";
15997
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015998 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15999 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016000 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
16001
16002 # problem summary
16003 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
16004 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
16005
16006 $Problem_Summary .= " <problems_with_types>\n";
16007 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
16008 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
16009 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
16010 $Problem_Summary .= " <safe>$T_Other</safe>\n";
16011 $Problem_Summary .= " </problems_with_types>\n";
16012
16013 $Problem_Summary .= " <problems_with_symbols>\n";
16014 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
16015 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
16016 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016017 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016018 $Problem_Summary .= " </problems_with_symbols>\n";
16019
16020 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016021 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016022 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016023 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016024 {
16025 $Problem_Summary .= " <impl>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016026 $Problem_Summary .= " <low>".keys(%CompatProblems_Impl)."</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016027 $Problem_Summary .= " </impl>\n";
16028 }
16029 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
16030
16031 return ($TestInfo.$TestResults.$Problem_Summary, "");
16032 }
16033 else
16034 { # HTML
16035 # test info
16036 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016037 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016038 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetLibraryFName</td></tr>\n";
16039
16040 my (@VInf1, @VInf2, $AddTestInfo) = ();
16041 if($Arch1 ne "unknown"
16042 and $Arch2 ne "unknown")
16043 { # CPU arch
16044 if($Arch1 eq $Arch2)
16045 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016046 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016047 }
16048 else
16049 { # go to the version number
16050 push(@VInf1, showArch($Arch1));
16051 push(@VInf2, showArch($Arch2));
16052 }
16053 }
16054 if($GccV1 ne "unknown"
16055 and $GccV2 ne "unknown"
16056 and $OStarget ne "windows")
16057 { # GCC version
16058 if($GccV1 eq $GccV2)
16059 { # go to the separate section
16060 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
16061 }
16062 else
16063 { # go to the version number
16064 push(@VInf1, "gcc ".$GccV1);
16065 push(@VInf2, "gcc ".$GccV2);
16066 }
16067 }
16068 # show long version names with GCC version and CPU architecture name (if different)
16069 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
16070 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
16071 $TestInfo .= $AddTestInfo;
16072 #if($COMMON_LANGUAGE{1}) {
16073 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
16074 #}
16075 if($ExtendedCheck) {
16076 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
16077 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016078 if($JoinReport)
16079 {
16080 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016081 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016082 }
16083 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016084 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016085 }
16086 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016087 $TestInfo .= "</table>\n";
16088
16089 # test results
16090 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016091 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016092
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016093 if(my @Headers = keys(%{$Registered_Headers{1}}))
16094 {
16095 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
16096 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
16097 }
16098 elsif($CheckObjectsOnly) {
16099 $TestResults .= "<tr><th>Total Header Files</th><td>0&#160;(not&#160;analyzed)</td></tr>\n";
16100 }
16101
16102 if(my @Sources = keys(%{$Registered_Sources{1}}))
16103 {
16104 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
16105 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
16106 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016107
16108 if(not $ExtendedCheck)
16109 {
16110 my $Libs_Link = "0";
16111 $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 +040016112 $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 +040016113 }
16114
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016115 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016116
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016117 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016118 if($JoinReport) {
16119 $META_DATA = "kind:".lc($Level).";".$META_DATA;
16120 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016121 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016122 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016123 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
16124 }
16125 else {
16126 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
16127 }
16128 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016129 $TestResults .= "</table>\n";
16130
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016131 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016132 # problem summary
16133 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016134 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016135 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
16136
16137 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016138 if($Added>0)
16139 {
16140 if($JoinReport) {
16141 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16142 }
16143 else {
16144 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16145 }
16146 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016147 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016148 $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 +040016149
16150 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016151 if($Removed>0)
16152 {
16153 if($JoinReport) {
16154 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16155 }
16156 else {
16157 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16158 }
16159 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016160 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016161 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
16162 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016163
16164 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016165 $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 +040016166 $TH_Link = "n/a" if($CheckObjectsOnly);
16167 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016168 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
16169 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016170
16171 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016172 $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 +040016173 $TM_Link = "n/a" if($CheckObjectsOnly);
16174 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016175 $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 +040016176
16177 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016178 $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 +040016179 $TL_Link = "n/a" if($CheckObjectsOnly);
16180 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016181 $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 +040016182
16183 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016184 $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 +040016185 $IH_Link = "n/a" if($CheckObjectsOnly);
16186 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016187 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
16188 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016189
16190 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016191 $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 +040016192 $IM_Link = "n/a" if($CheckObjectsOnly);
16193 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016194 $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 +040016195
16196 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016197 $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 +040016198 $IL_Link = "n/a" if($CheckObjectsOnly);
16199 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016200 $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 +040016201
16202 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016203 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16204 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016205 }
16206 $ChangedConstants_Link = "n/a" if($CheckObjectsOnly);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016207 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016208 $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 +040016209
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016210 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016211 {
16212 my $ChangedImpl_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016213 $ChangedImpl_Link = "<a href='#Changed_Implementation' style='color:Blue;'>".keys(%CompatProblems_Impl)."</a>" if(keys(%CompatProblems_Impl)>0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016214 $ChangedImpl_Link = "n/a" if($CheckHeadersOnly);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016215 $META_DATA .= "changed_implementation:".keys(%CompatProblems_Impl).";";
16216 $Problem_Summary .= "<tr><th>Problems with<br/>Implementation</th><td>Low</td><td".getStyle("Imp", "L", int(keys(%CompatProblems_Impl))).">$ChangedImpl_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016217 }
16218 # Safe Changes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016219 if($T_Other and not $CheckObjectsOnly)
16220 {
16221 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016222 $Problem_Summary .= "<tr><th>Other Changes<br/>in Data Types</th><td>-</td><td".getStyle("T", "S", $T_Other).">$TS_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016223 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016224
16225 if($I_Other and not $CheckObjectsOnly)
16226 {
16227 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016228 $Problem_Summary .= "<tr><th>Other Changes<br/>in Symbols</th><td>-</td><td".getStyle("I", "S", $I_Other).">$IS_Link</td></tr>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016229 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016230
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016231 if($C_Other and not $CheckObjectsOnly)
16232 {
16233 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
16234 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
16235 }
16236
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016237 $META_DATA .= "tool_version:$TOOL_VERSION";
16238 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016239 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016240 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16241 }
16242}
16243
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016244sub getStyle($$$)
16245{
16246 my ($Subj, $Act, $Num) = @_;
16247 my %Style = (
16248 "A"=>"new",
16249 "R"=>"failed",
16250 "S"=>"passed",
16251 "L"=>"warning",
16252 "M"=>"failed",
16253 "H"=>"failed"
16254 );
16255 if($Num>0) {
16256 return " class='".$Style{$Act}."'";
16257 }
16258 return "";
16259}
16260
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016261sub show_number($)
16262{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016263 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016264 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016265 my $Num = cut_off_number($_[0], 2, 0);
16266 if($Num eq "0")
16267 {
16268 foreach my $P (3 .. 7)
16269 {
16270 $Num = cut_off_number($_[0], $P, 1);
16271 if($Num ne "0") {
16272 last;
16273 }
16274 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016275 }
16276 if($Num eq "0") {
16277 $Num = $_[0];
16278 }
16279 return $Num;
16280 }
16281 return $_[0];
16282}
16283
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016284sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016285{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016286 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016287 if($num!~/\./)
16288 {
16289 $num .= ".";
16290 foreach (1 .. $digs_to_cut-1) {
16291 $num .= "0";
16292 }
16293 }
16294 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16295 {
16296 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16297 $num .= "0";
16298 }
16299 }
16300 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16301 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16302 }
16303 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016304 if($z) {
16305 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16306 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016307 return $num;
16308}
16309
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016310sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016311{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016312 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016313 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016314
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016315 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016316 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16317 {
16318 my $Header = $Constants{1}{$Constant}{"Header"};
16319 if(not $Header)
16320 { # added
16321 $Header = $Constants{2}{$Constant}{"Header"}
16322 }
16323
16324 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16325 {
16326 if(not defined $CompatRules{$Level}{$Kind}) {
16327 next;
16328 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016329 if($TargetSeverity ne $CompatRules{$Level}{$Kind}{"Severity"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016330 next;
16331 }
16332 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16333 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016334 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016335
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016336 if($ReportFormat eq "xml")
16337 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016338 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016339 {
16340 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016341 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016342 {
16343 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016344 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16345 {
16346 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16347 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16348 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016349
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016350 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16351 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16352 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016353 if($Overcome) {
16354 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16355 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016356 $CHANGED_CONSTANTS .= " </problem>\n";
16357 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016358 $CHANGED_CONSTANTS .= " </constant>\n";
16359 }
16360 $CHANGED_CONSTANTS .= " </header>\n";
16361 }
16362 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16363 }
16364 else
16365 { # HTML
16366 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016367 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016368 {
16369 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016370 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016371 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016372 my $Report = "";
16373
16374 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16375 {
16376 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16377 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16378 $Report .= "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16379 $Number += 1;
16380 }
16381 if($Report)
16382 {
16383 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n";
16384 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16385 $Report = insertIDs($Report);
16386 }
16387 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016388 }
16389 $CHANGED_CONSTANTS .= "<br/>\n";
16390 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016391 if($CHANGED_CONSTANTS)
16392 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016393 my $Title = "Problems with Constants, $TargetSeverity Severity";
16394 if($TargetSeverity eq "Safe")
16395 { # Safe Changes
16396 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016397 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016398 $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 +040016399 }
16400 }
16401 return $CHANGED_CONSTANTS;
16402}
16403
16404sub get_Report_Impl()
16405{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016406 my $CHANGED_IMPLEMENTATION = "";
16407 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016408 foreach my $Interface (sort keys(%CompatProblems_Impl))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016409 {
16410 my $HeaderName = $CompleteSignature{1}{$Interface}{"Header"};
16411 my $DyLib = $Symbol_Library{1}{$Interface};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016412 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016413 }
16414 my $Changed_Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016415 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016416 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016417 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016418 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016419 my %NameSpaceSymbols = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016420 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016421 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016422 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016423 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016424 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016425 $CHANGED_IMPLEMENTATION .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016426 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016427 foreach my $Interface (@SortedInterfaces)
16428 {
16429 $Changed_Number += 1;
16430 my $Signature = get_Signature($Interface, 1);
16431 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016432 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016433 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016434 $CHANGED_IMPLEMENTATION .= $ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Interface</b>]</span>".$CompatProblems_Impl{$Interface}{"Diff"}."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016435 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016436 $CHANGED_IMPLEMENTATION .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016437 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016438 }
16439 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016440 if($CHANGED_IMPLEMENTATION)
16441 {
16442 $CHANGED_IMPLEMENTATION = insertIDs($CHANGED_IMPLEMENTATION);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016443 $CHANGED_IMPLEMENTATION = "<a name='Changed_Implementation'></a><h2>Problems with Implementation ($Changed_Number)</h2><hr/>\n".$CHANGED_IMPLEMENTATION.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016444 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016445
16446 # clean memory
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016447 %CompatProblems_Impl = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016448
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016449 return $CHANGED_IMPLEMENTATION;
16450}
16451
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016452sub getTitle($$$)
16453{
16454 my ($Header, $Library, $NameSpace) = @_;
16455 my $Title = "";
16456 if($Library and $Library!~/\.\w+\Z/) {
16457 $Library .= " (.$LIB_EXT)";
16458 }
16459 if($Header and $Library)
16460 {
16461 $Title .= "<span class='h_name'>$Header</span>";
16462 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16463 }
16464 elsif($Library) {
16465 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16466 }
16467 elsif($Header) {
16468 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16469 }
16470 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016471 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016472 }
16473 return $Title;
16474}
16475
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016476sub get_Report_Added($)
16477{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016478 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016479 my $ADDED_INTERFACES = "";
16480 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016481 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016482 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016483 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016484 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016485 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016486 {
16487 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16488 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016489 if($Level eq "Source" and $ReportFormat eq "html")
16490 { # do not show library name in HTML report
16491 $DyLib = "";
16492 }
16493 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016494 }
16495 }
16496 }
16497 if($ReportFormat eq "xml")
16498 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016499 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016500 {
16501 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016502 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016503 {
16504 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016505 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016506 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16507 }
16508 $ADDED_INTERFACES .= " </library>\n";
16509 }
16510 $ADDED_INTERFACES .= " </header>\n";
16511 }
16512 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16513 }
16514 else
16515 { # HTML
16516 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016517 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016518 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016519 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016520 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016521 my %NameSpaceSymbols = ();
16522 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016523 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016524 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016525 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016526 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016527 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16528 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016529 foreach my $Interface (@SortedInterfaces)
16530 {
16531 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016532 my $Signature = get_Signature($Interface, 2);
16533 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016534 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016535 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016536 if($Interface=~/\A(_Z|\?)/)
16537 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016538 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016539 $ADDED_INTERFACES .= insertIDs($ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Interface</b>]</span><br/><br/>".$ContentDivEnd."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016540 }
16541 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016542 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016543 }
16544 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016545 else
16546 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016547 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016548 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016549 }
16550 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016551 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016552 }
16553 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016554 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016555 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016556 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016557 }
16558 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016559 if($ADDED_INTERFACES)
16560 {
16561 my $Anchor = "<a name='Added'></a>";
16562 if($JoinReport) {
16563 $Anchor = "<a name='".$Level."_Added'></a>";
16564 }
16565 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016566 }
16567 }
16568 return $ADDED_INTERFACES;
16569}
16570
16571sub get_Report_Removed($)
16572{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016573 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016574 my $REMOVED_INTERFACES = "";
16575 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016576 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016577 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016578 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016579 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016580 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016581 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016582 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16583 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016584 if($Level eq "Source" and $ReportFormat eq "html")
16585 { # do not show library name in HTML report
16586 $DyLib = "";
16587 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016588 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016589 }
16590 }
16591 }
16592 if($ReportFormat eq "xml")
16593 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016594 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016595 {
16596 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016597 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016598 {
16599 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016600 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16601 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016602 }
16603 $REMOVED_INTERFACES .= " </library>\n";
16604 }
16605 $REMOVED_INTERFACES .= " </header>\n";
16606 }
16607 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16608 }
16609 else
16610 { # HTML
16611 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016612 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016613 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016614 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016615 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016616 my %NameSpaceSymbols = ();
16617 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016618 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016619 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016620 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016621 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016622 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16623 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016624 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016625 {
16626 $Removed_Number += 1;
16627 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016628 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016629 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016630 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016631 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016632 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016633 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016634 if($Signature) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016635 $REMOVED_INTERFACES .= insertIDs($ContentSpanStart.highLight_Signature_Italic_Color($Signature).$ContentSpanEnd."<br/>\n".$ContentDivStart."<span class='mangled'>[symbol: <b>$Symbol</b>]</span><br/><br/>".$ContentDivEnd."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016636 }
16637 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016638 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016639 }
16640 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016641 else
16642 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016643 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016644 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016645 }
16646 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016647 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016648 }
16649 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016650 }
16651 }
16652 $REMOVED_INTERFACES .= "<br/>\n";
16653 }
16654 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016655 if($REMOVED_INTERFACES)
16656 {
16657 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16658 if($JoinReport) {
16659 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16660 }
16661 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016662 }
16663 }
16664 return $REMOVED_INTERFACES;
16665}
16666
16667sub getXmlParams($$)
16668{
16669 my ($Content, $Problem) = @_;
16670 return "" if(not $Content or not $Problem);
16671 my %XMLparams = ();
16672 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16673 {
16674 my $Macro = "\@".lc($Attr);
16675 if($Content=~/\Q$Macro\E/) {
16676 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16677 }
16678 }
16679 my @PString = ();
16680 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016681 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016682 }
16683 if(@PString) {
16684 return " ".join(" ", @PString);
16685 }
16686 else {
16687 return "";
16688 }
16689}
16690
16691sub addMarkup($)
16692{
16693 my $Content = $_[0];
16694 # auto-markup
16695 $Content=~s/\n[ ]*//; # spaces
16696 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16697 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016698 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016699 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16700 if($Content=~/\ANOTE:/)
16701 { # notes
16702 $Content=~s!(NOTE):!<b>$1</b>:!g;
16703 }
16704 else {
16705 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16706 }
16707 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16708 my @Keywords = (
16709 "void",
16710 "const",
16711 "static",
16712 "restrict",
16713 "volatile",
16714 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016715 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016716 );
16717 my $MKeys = join("|", @Keywords);
16718 foreach (@Keywords) {
16719 $MKeys .= "|non-".$_;
16720 }
16721 $Content=~s!(added\s*|to\s*|from\s*|became\s*)($MKeys)([^\w-]|\Z)!$1<b>$2</b>$3!ig; # intrinsic types, modifiers
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016722
16723 # Markdown
16724 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16725 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016726 return $Content;
16727}
16728
16729sub applyMacroses($$$$)
16730{
16731 my ($Level, $Kind, $Content, $Problem) = @_;
16732 return "" if(not $Content or not $Problem);
16733 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16734 $Content = addMarkup($Content);
16735 # macros
16736 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16737 {
16738 my $Macro = "\@".lc($Attr);
16739 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016740 if(not defined $Value
16741 or $Value eq "") {
16742 next;
16743 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016744 if($Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016745 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016746 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
16747 $Value=~s/\s\w+(\)|,)/$1/g; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016748 $Value = black_name($Value);
16749 }
16750 elsif($Value=~/\s/) {
16751 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16752 }
16753 elsif($Value=~/\A\d+\Z/
16754 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16755 { # bits to bytes
16756 if($Value % $BYTE_SIZE)
16757 { # bits
16758 if($Value==1) {
16759 $Value = "<b>".$Value."</b> bit";
16760 }
16761 else {
16762 $Value = "<b>".$Value."</b> bits";
16763 }
16764 }
16765 else
16766 { # bytes
16767 $Value /= $BYTE_SIZE;
16768 if($Value==1) {
16769 $Value = "<b>".$Value."</b> byte";
16770 }
16771 else {
16772 $Value = "<b>".$Value."</b> bytes";
16773 }
16774 }
16775 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016776 else
16777 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016778 $Value = "<b>".htmlSpecChars($Value)."</b>";
16779 }
16780 $Content=~s/\Q$Macro\E/$Value/g;
16781 }
16782
16783 if($Content=~/(\A|[^\@\w])\@\w/)
16784 {
16785 if(not $IncompleteRules{$Level}{$Kind})
16786 { # only one warning
16787 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16788 $IncompleteRules{$Level}{$Kind} = 1;
16789 }
16790 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016791 return $Content;
16792}
16793
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016794sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016795{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016796 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016797 my $INTERFACE_PROBLEMS = "";
16798 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016799
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016800 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016801 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016802 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16803 if($SV and defined $CompatProblems{$Level}{$SN}) {
16804 next;
16805 }
16806 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016807 {
16808 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016809 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016810 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016811 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16812 my $DyLib = $Symbol_Library{1}{$Symbol};
16813 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016814 { # Symbol with Version
16815 $DyLib = $Symbol_Library{1}{$VSym};
16816 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016817 if(not $DyLib)
16818 { # const global data
16819 $DyLib = "";
16820 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016821 if($Level eq "Source" and $ReportFormat eq "html")
16822 { # do not show library name in HTML report
16823 $DyLib = "";
16824 }
16825 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16826 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016827 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016828 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
16829 if($Severity ne $TargetSeverity) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016830 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016831 }
16832 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016833 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16834 {
16835 delete($SymbolChanges{$Symbol}{$Kind});
16836 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016837 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016838 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016839 }
16840 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016841 if(not keys(%{$SymbolChanges{$Symbol}})) {
16842 delete($SymbolChanges{$Symbol});
16843 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016844 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016845
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016846 if($ReportFormat eq "xml")
16847 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016848 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016849 {
16850 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016851 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016852 {
16853 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016854 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$ReportMap{$HeaderName}{$DyLib}});
16855 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016856 {
16857 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16858 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16859 {
16860 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16861 {
16862 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016863 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016864
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016865 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16866 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16867 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16868 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16869 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040016870 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
16871 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16872 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016873 $INTERFACE_PROBLEMS .= " </problem>\n";
16874 }
16875 }
16876 $INTERFACE_PROBLEMS .= " </symbol>\n";
16877 }
16878 $INTERFACE_PROBLEMS .= " </library>\n";
16879 }
16880 $INTERFACE_PROBLEMS .= " </header>\n";
16881 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016882 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016883 }
16884 else
16885 { # HTML
16886 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016887 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016888 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016889 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016890 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016891 my (%NameSpaceSymbols, %NewSignature) = ();
16892 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016893 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016894 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016895 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016896 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016897 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016898 my @SortedInterfaces = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016899 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016900 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016901 my $Signature = get_Signature($Symbol, 1);
16902 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016903 my $ProblemNum = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016904 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016905 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016906 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016907 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016908 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016909 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016910 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016911 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016912 }
16913 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16914 {
16915 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016916 $SYMBOL_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>".$Effect."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016917 $ProblemNum += 1;
16918 $ProblemsNum += 1;
16919 }
16920 }
16921 }
16922 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016923 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016924 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016925 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016926 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016927 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016928 }
16929 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016930 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016931 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016932 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16933 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16934 if($NewSignature{$Symbol})
16935 { # argument list changed to
16936 $INTERFACE_PROBLEMS .= "\n<span class='new_sign_lbl'>changed to:</span><br/><span class='new_sign'>".highLight_Signature_Italic_Color($NewSignature{$Symbol})."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016937 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016938 if($Symbol=~/\A(_Z|\?)/) {
16939 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16940 }
16941 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n";
16942 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016943 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016944 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016945 }
16946 }
16947 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016948 $INTERFACE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016949 }
16950 }
16951 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016952
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016953 if($INTERFACE_PROBLEMS)
16954 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016955 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16956 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16957 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016958 { # Safe Changes
16959 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016960 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016961 $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 +040016962 }
16963 }
16964 return $INTERFACE_PROBLEMS;
16965}
16966
16967sub get_Report_TypeProblems($$)
16968{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016969 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016970 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016971 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016972
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016973 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016974 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016975 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016976 {
16977 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16978 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016979 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016980 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016981 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016982 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040016983 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016984
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016985 if($Severity eq "Safe"
16986 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016987 next;
16988 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016989
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016990 if(my $MaxSeverity = $Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target})
16991 {
16992 if($Severity_Val{$MaxSeverity}>$Severity_Val{$Severity})
16993 { # select a problem with the highest priority
16994 next;
16995 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016996 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040016997
16998 $TypeChanges{$TypeName}{$Kind}{$Location} = $CompatProblems{$Level}{$Interface}{$Kind}{$Location};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016999 }
17000 }
17001 }
17002 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017003
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017004 my %Kinds_Locations = ();
17005 foreach my $TypeName (keys(%TypeChanges))
17006 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017007 my %Kind_Target = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017008 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
17009 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017010 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017011 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017012 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017013 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017014 { # other priority
17015 delete($TypeChanges{$TypeName}{$Kind}{$Location});
17016 next;
17017 }
17018 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
17019 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017020 if($Kind_Target{$Kind}{$Target})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017021 { # duplicate target
17022 delete($TypeChanges{$TypeName}{$Kind}{$Location});
17023 next;
17024 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017025 $Kind_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017026 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017027 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017028 }
17029 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
17030 delete($TypeChanges{$TypeName}{$Kind});
17031 }
17032 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017033 if(not keys(%{$TypeChanges{$TypeName}})) {
17034 delete($TypeChanges{$TypeName});
17035 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017036 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017037
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017038 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 +040017039 if($ReportFormat eq "xml")
17040 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017041 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017042 {
17043 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017044 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017045 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017046 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017047 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
17048 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017049 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017050 {
17051 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
17052 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
17053 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
17054 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
17055 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
17056 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017057 if(my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"}) {
17058 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
17059 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017060 $TYPE_PROBLEMS .= " </problem>\n";
17061 }
17062 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017063 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017064 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017065 $TYPE_PROBLEMS .= showVTables($TypeName);
17066 }
17067 $TYPE_PROBLEMS .= " </type>\n";
17068 }
17069 $TYPE_PROBLEMS .= " </header>\n";
17070 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017071 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017072 }
17073 else
17074 { # HTML
17075 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017076 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017077 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017078 my (%NameSpace_Type) = ();
17079 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017080 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017081 }
17082 foreach my $NameSpace (sort keys(%NameSpace_Type))
17083 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017084 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017085 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 +040017086 foreach my $TypeName (@SortedTypes)
17087 {
17088 my $ProblemNum = 1;
17089 my $TYPE_REPORT = "";
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017090
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017091 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
17092 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017093 foreach my $Location (sort {cmpLocations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017094 {
17095 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
17096 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
17097 {
17098 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
17099 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
17100 $ProblemNum += 1;
17101 $ProblemsNum += 1;
17102 }
17103 }
17104 }
17105 $ProblemNum -= 1;
17106 if($TYPE_REPORT)
17107 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017108 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017109 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017110 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017111 $ShowVTables = showVTables($TypeName);
17112 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017113
17114 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017115 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
17116 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
17117 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
17118 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017119 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017120 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017121 }
17122 }
17123 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017124 $TYPE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017125 }
17126 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017127
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017128 if($TYPE_PROBLEMS)
17129 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017130 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
17131 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017132 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017133 { # Safe Changes
17134 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017135 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017136 $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 +040017137 }
17138 }
17139 return $TYPE_PROBLEMS;
17140}
17141
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017142sub show_Type($$$)
17143{
17144 my ($Name, $Html, $LibVersion) = @_;
17145 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
17146 $TType = lc($TType);
17147 if($TType=~/struct|union|enum/) {
17148 $Name=~s/\A\Q$TType\E //g;
17149 }
17150 if($Html) {
17151 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
17152 }
17153 else {
17154 $Name = $TType." ".$Name;
17155 }
17156 return $Name;
17157}
17158
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017159sub get_Anchor($$$)
17160{
17161 my ($Kind, $Level, $Severity) = @_;
17162 if($JoinReport)
17163 {
17164 if($Severity eq "Safe") {
17165 return "Other_".$Level."_Changes_In_".$Kind."s";
17166 }
17167 else {
17168 return $Kind."_".$Level."_Problems_".$Severity;
17169 }
17170 }
17171 else
17172 {
17173 if($Severity eq "Safe") {
17174 return "Other_Changes_In_".$Kind."s";
17175 }
17176 else {
17177 return $Kind."_Problems_".$Severity;
17178 }
17179 }
17180}
17181
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017182sub showVTables($)
17183{
17184 my $TypeName = $_[0];
17185 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017186 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017187 if(defined $Type1{"VTable"}
17188 and keys(%{$Type1{"VTable"}}))
17189 {
17190 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017191 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017192 if(defined $Type2{"VTable"}
17193 and keys(%{$Type2{"VTable"}}))
17194 {
17195 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17196 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017197 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017198 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017199 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17200 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017201 }
17202 my $VTABLES = "";
17203 if($ReportFormat eq "xml")
17204 { # XML
17205 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017206 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017207 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017208 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017209 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17210 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017211 $VTABLES .= " </entry>\n";
17212 }
17213 $VTABLES .= " </vtable>\n\n";
17214 }
17215 else
17216 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017217 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017218 $VTABLES .= "<tr><th width='2%'>Offset</th>";
17219 $VTABLES .= "<th width='45%'>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
17220 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017221 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017222 {
17223 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017224 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017225 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017226 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017227 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017228 $Color1 = " class='failed'";
17229 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017230 }
17231 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017232 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017233 }
17234 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017235 $VTABLES .= "<tr><th>".$Index."</th>\n";
17236 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17237 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017238 }
17239 $VTABLES .= "</table><br/>\n";
17240 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017241 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017242 }
17243 return $VTABLES;
17244 }
17245 }
17246 return "";
17247}
17248
17249sub simpleVEntry($)
17250{
17251 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017252 if(not defined $VEntry
17253 or $VEntry eq "") {
17254 return "";
17255 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017256 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17257 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17258 if($VEntry=~/\A_ZThn.+\Z/) {
17259 $VEntry = "non-virtual thunk";
17260 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017261 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017262 # support for old GCC versions
17263 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17264 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17265 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017266 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17267 return $VEntry;
17268}
17269
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017270sub adjustParamPos($$$)
17271{
17272 my ($Pos, $Symbol, $LibVersion) = @_;
17273 if(defined $CompleteSignature{$LibVersion}{$Symbol})
17274 {
17275 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Static"}
17276 and $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
17277 {
17278 return $Pos-1;
17279 }
17280
17281 return $Pos;
17282 }
17283
17284 return undef;
17285}
17286
17287sub getParamPos($$$)
17288{
17289 my ($Name, $Symbol, $LibVersion) = @_;
17290
17291 if(defined $CompleteSignature{$LibVersion}{$Symbol}
17292 and defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"})
17293 {
17294 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17295 foreach (keys(%{$Info->{"Param"}}))
17296 {
17297 if($Info->{"Param"}{$_}{"name"} eq $Name)
17298 {
17299 return $_;
17300 }
17301 }
17302 }
17303
17304 return undef;
17305}
17306
17307sub getParamName($)
17308{
17309 my $Loc = $_[0];
17310 $Loc=~s/\->.*//g;
17311 return $Loc;
17312}
17313
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017314sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017315{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017316 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017317 my $LIMIT = 1000;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017318
17319 if(defined $AffectLimit)
17320 {
17321 $LIMIT = $AffectLimit;
17322 }
17323 else
17324 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017325 if($#{$Syms}>=1999)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017326 { # reduce size of the report
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017327 $AffectLimit = 10;
17328
17329 printMsg("WARNING", "reducing limit of affected symbols shown in the report to $AffectLimit");
17330 $LIMIT = $AffectLimit;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017331 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017332 }
17333 my %SProblems = ();
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017334 LOOP: foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017335 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017336 if(index($Symbol, "_Z")==0
17337 and $Symbol=~/(C2|D2|D0)[EI]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017338 { # duplicated problems for C2 constructors, D2 and D0 destructors
17339 next;
17340 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017341
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017342 my ($MinPath_Length, $ProblemLocation_Last) = (-1, "");
17343 my $Severity_Max = 0;
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017344
17345 foreach my $Kind (keys(%{$Kinds_Locations}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017346 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017347 if(not defined $CompatProblems{$Level}{$Symbol}
17348 or not defined $CompatProblems{$Level}{$Symbol}{$Kind}) {
17349 next;
17350 }
17351
17352 foreach my $Location (keys(%{$Kinds_Locations->{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017353 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017354 if(keys(%SProblems)>$LIMIT) {
17355 last LOOP;
17356 }
17357
17358 if(not defined $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017359 next;
17360 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017361
17362 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17363 if($Level eq "Source")
17364 { # remove symbol version
17365 $Symbol=$SN;
17366 }
17367
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017368 if($SV and defined $CompatProblems{$Level}{$SN}
17369 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Location})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017370 { # duplicated problems for versioned symbols
17371 next;
17372 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017373
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017374 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017375 if($Type_Name ne $Target_TypeName) {
17376 next;
17377 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017378
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017379 my $PName = getParamName($Location);
17380 my $PPos = adjustParamPos(getParamPos($PName, $Symbol, 1), $Symbol, 1);
17381
17382 my $Severity = $CompatRules{$Level}{$Kind}{"Severity"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017383 my $Path_Length = 0;
17384 my $ProblemLocation = $Location;
17385 if($Type_Name) {
17386 $ProblemLocation=~s/->\Q$Type_Name\E\Z//g;
17387 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017388 while($ProblemLocation=~/\-\>/g) {
17389 $Path_Length += 1;
17390 }
17391 if($MinPath_Length==-1 or ($Path_Length<=$MinPath_Length and $Severity_Val{$Severity}>$Severity_Max)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017392 or (cmpLocations($ProblemLocation, $ProblemLocation_Last) and $Severity_Val{$Severity}==$Severity_Max))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017393 {
17394 $MinPath_Length = $Path_Length;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017395 $Severity_Max = $Severity_Val{$Severity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017396 $ProblemLocation_Last = $ProblemLocation;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017397 %{$SProblems{$Symbol}} = (
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017398 "Descr"=>getAffectDesc($Level, $Symbol, $Kind, $Location),
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017399 "Severity_Max"=>$Severity_Max,
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017400 "Signature"=>get_Signature($Symbol, 1),
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017401 "Position"=>$PPos,
17402 "Param_Name"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017403 "Location"=>$Location
17404 );
17405 }
17406 }
17407 }
17408 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017409 my @Symbols = keys(%SProblems);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017410 @Symbols = sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} @Symbols;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017411 @Symbols = sort {$SProblems{$b}{"Severity_Max"}<=>$SProblems{$a}{"Severity_Max"}} @Symbols;
17412 if($#Symbols+1>$LIMIT)
17413 { # remove last element
17414 pop(@Symbols);
17415 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017416 my $Affected = "";
17417 if($ReportFormat eq "xml")
17418 { # XML
17419 $Affected .= " <affected>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017420 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017421 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017422 my $Param_Name = $SProblems{$Symbol}{"Param_Name"};
17423 my $Description = $SProblems{$Symbol}{"Descr"};
17424 my $Location = $SProblems{$Symbol}{"Location"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017425 my $Target = "";
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017426 if($Param_Name)
17427 {
17428 $Target .= " param=\"$Param_Name\"";
17429 $Description=~s/parameter $Param_Name /parameter \@param /;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017430 }
17431 elsif($Location=~/\Aretval(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017432 $Target .= " affected=\"retval\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017433 }
17434 elsif($Location=~/\Athis(\-|\Z)/i) {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017435 $Target .= " affected=\"this\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017436 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017437
17438 if($Description=~s/\AField ([^\s]+) /Field \@field /) {
17439 $Target .= " field=\"$1\"";
17440 }
17441
17442 $Affected .= " <symbol name=\"$Symbol\"$Target>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017443 $Affected .= " <comment>".xmlSpecChars($Description)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017444 $Affected .= " </symbol>\n";
17445 }
17446 $Affected .= " </affected>\n";
17447 }
17448 else
17449 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017450 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017451 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017452 my $Description = $SProblems{$Symbol}{"Descr"};
17453 my $Signature = $SProblems{$Symbol}{"Signature"};
17454 my $Pos = $SProblems{$Symbol}{"Position"};
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017455 $Affected .= "<span class='iname_a'>".highLight_Signature_PPos_Italic($Signature, $Pos, 1, 0, 0)."</span><br/><div class='affect'>".htmlSpecChars($Description)."</div>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017456 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017457 if(keys(%SProblems)>$LIMIT) {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017458 $Affected .= " ...<br/>"; # and others ...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017459 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017460 $Affected = "<div class='affected'>".$Affected."</div>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017461 if($Affected)
17462 {
17463 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017464 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".(keys(%SProblems)>$LIMIT?">".$LIMIT:keys(%SProblems)).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017465 }
17466 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017467
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017468 return $Affected;
17469}
17470
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017471sub cmpLocations($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017472{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017473 my ($L1, $L2) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017474 if($L2=~/\A(retval|this)\b/
17475 and $L1!~/\A(retval|this)\b/)
17476 {
17477 if($L1!~/\-\>/) {
17478 return 1;
17479 }
17480 elsif($L2=~/\-\>/) {
17481 return 1;
17482 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017483 }
17484 return 0;
17485}
17486
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017487sub getAffectDesc($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017488{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017489 my ($Level, $Symbol, $Kind, $Location) = @_;
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017490
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017491 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017492
17493 my $Location_I = $Location;
17494 $Location=~s/\A(.*)\-\>(.+?)\Z/$1/; # without the latest affected field
17495
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017496 my @Sentence = ();
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017497
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017498 if($Kind eq "Overridden_Virtual_Method"
17499 or $Kind eq "Overridden_Virtual_Method_B") {
17500 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17501 }
17502 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17503 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017504 my %SymInfo = %{$CompleteSignature{1}{$Symbol}};
17505
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017506 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17507 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017508 my $METHOD_TYPE = $SymInfo{"Constructor"}?"constructor":"method";
17509 my $ClassName = $TypeInfo{1}{$SymInfo{"Class"}}{"Name"};
17510
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017511 if($ClassName eq $Problem{"Type_Name"}) {
17512 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17513 }
17514 else {
17515 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17516 }
17517 }
17518 else
17519 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017520 my $TypeID = undef;
17521
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017522 if($Location=~/retval/)
17523 { # return value
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017524 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017525 push(@Sentence, "Field \'".$Location."\' in return value");
17526 }
17527 else {
17528 push(@Sentence, "Return value");
17529 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017530
17531 $TypeID = $SymInfo{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017532 }
17533 elsif($Location=~/this/)
17534 { # "this" pointer
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017535 if(index($Location, "->")!=-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017536 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17537 }
17538 else {
17539 push(@Sentence, "\'this\' pointer");
17540 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017541
17542 $TypeID = $SymInfo{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017543 }
17544 else
17545 { # parameters
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017546
17547 my $PName = getParamName($Location);
17548 my $PPos = getParamPos($PName, $Symbol, 1);
17549
17550 if(index($Location, "->")!=-1) {
17551 push(@Sentence, "Field \'".$Location."\' in ".showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017552 }
17553 else {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017554 push(@Sentence, showPos(adjustParamPos($PPos, $Symbol, 1))." parameter");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017555 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017556 if($PName) {
17557 push(@Sentence, "\'".$PName."\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017558 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017559
17560 $TypeID = $SymInfo{"Param"}{$PPos}{"type"};
17561 }
17562
17563 if($Location!~/this/)
17564 {
17565 if(my %PureType = get_PureType($TypeID, $TypeInfo{1}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017566 {
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017567 if($PureType{"Type"} eq "Pointer") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017568 push(@Sentence, "(pointer)");
17569 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017570 elsif($PureType{"Type"} eq "Ref") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017571 push(@Sentence, "(reference)");
17572 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017573 }
17574 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017575
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017576 if($Location eq "this") {
17577 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17578 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017579 else
17580 {
17581 my $Location_T = $Location;
17582 $Location_T=~s/\A\w+(\->|\Z)//; # location in type
17583
17584 my $TypeID_Problem = $TypeID;
17585 if($Location_T) {
17586 $TypeID_Problem = getFieldType($Location_T, $TypeID, 1);
17587 }
17588
17589 if($TypeInfo{1}{$TypeID_Problem}{"Name"} eq $Problem{"Type_Name"}) {
17590 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17591 }
17592 else {
17593 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17594 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017595 }
17596 }
17597 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017598 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017599 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 +040017600 }
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017601
17602 my $Sent = join(" ", @Sentence);
17603
17604 if($ReportFormat eq "xml")
17605 {
17606 $Sent=~s/->/./g;
17607 $Sent=~s/'//g;
17608 }
17609
17610 return $Sent;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017611}
17612
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017613sub getFieldType($$$)
17614{
17615 my ($Location, $TypeId, $LibVersion) = @_;
17616
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040017617 my @Fields = split(/\->/, $Location);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040017618
17619 foreach my $Name (@Fields)
17620 {
17621 my %Info = get_BaseType($TypeId, $LibVersion);
17622
17623 foreach my $Pos (keys(%{$Info{"Memb"}}))
17624 {
17625 if($Info{"Memb"}{$Pos}{"name"} eq $Name)
17626 {
17627 $TypeId = $Info{"Memb"}{$Pos}{"type"};
17628 last;
17629 }
17630 }
17631 }
17632
17633 return $TypeId;
17634}
17635
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017636sub get_XmlSign($$)
17637{
17638 my ($Symbol, $LibVersion) = @_;
17639 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17640 my $Report = "";
17641 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17642 {
17643 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017644 my $Type = $Info->{"Param"}{$Pos}{"type"};
17645 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017646 foreach my $Typedef (keys(%ChangedTypedef))
17647 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017648 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17649 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17650 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017651 }
17652 $Report .= " <param pos=\"$Pos\">\n";
17653 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017654 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017655 $Report .= " </param>\n";
17656 }
17657 if(my $Return = $Info->{"Return"})
17658 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017659 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017660 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017661 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017662 $Report .= " </retval>\n";
17663 }
17664 return $Report;
17665}
17666
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017667sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017668{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017669 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017670 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017671 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017672 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017673 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17674 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017675 next;
17676 }
17677 $Report .= " <symbol name=\"$Symbol\">\n";
17678 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017679 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017680 {
17681 if(defined $CompleteSignature{1}{$Symbol}
17682 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17683 {
17684 $P1 = get_XmlSign($Symbol, 1);
17685 $S1 = get_Signature($Symbol, 1);
17686 }
17687 elsif($Symbol=~/\A(_Z|\?)/) {
17688 $S1 = $tr_name{$Symbol};
17689 }
17690 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017691 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017692 {
17693 if(defined $CompleteSignature{2}{$Symbol}
17694 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17695 {
17696 $P2 = get_XmlSign($Symbol, 2);
17697 $S2 = get_Signature($Symbol, 2);
17698 }
17699 elsif($Symbol=~/\A(_Z|\?)/) {
17700 $S2 = $tr_name{$Symbol};
17701 }
17702 }
17703 if($S1)
17704 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017705 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017706 $Report .= $P1;
17707 $Report .= " </old>\n";
17708 }
17709 if($S2 and $S2 ne $S1)
17710 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017711 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017712 $Report .= $P2;
17713 $Report .= " </new>\n";
17714 }
17715 $Report .= " </symbol>\n";
17716 }
17717 $Report .= "</symbols_info>\n";
17718 return $Report;
17719}
17720
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017721sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017722{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017723 my ($Level, $Report) = @_;
17724 if($ReportFormat eq "xml") {
17725 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017726 }
17727 if($StdOut)
17728 { # --stdout option
17729 print STDOUT $Report;
17730 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017731 else
17732 {
17733 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017734 mkpath(get_dirname($RPath));
17735
17736 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17737 print REPORT $Report;
17738 close(REPORT);
17739
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017740 if($Browse or $OpenReport)
17741 { # open in browser
17742 openReport($RPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017743 if($JoinReport or $DoubleReport)
17744 {
17745 if($Level eq "Binary")
17746 { # wait to open a browser
17747 sleep(1);
17748 }
17749 }
17750 }
17751 }
17752}
17753
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017754sub openReport($)
17755{
17756 my $Path = $_[0];
17757 my $Cmd = "";
17758 if($Browse)
17759 { # user-defined browser
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017760 $Cmd = $Browse." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017761 }
17762 if(not $Cmd)
17763 { # default browser
17764 if($OSgroup eq "macos") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017765 $Cmd = "open \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017766 }
17767 elsif($OSgroup eq "windows") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017768 $Cmd = "start ".path_format($Path, $OSgroup);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017769 }
17770 else
17771 { # linux, freebsd, solaris
17772 my @Browsers = (
17773 "x-www-browser",
17774 "sensible-browser",
17775 "firefox",
17776 "opera",
17777 "xdg-open",
17778 "lynx",
17779 "links"
17780 );
17781 foreach my $Br (@Browsers)
17782 {
17783 if($Br = get_CmdPath($Br))
17784 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017785 $Cmd = $Br." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017786 last;
17787 }
17788 }
17789 }
17790 }
17791 if($Cmd)
17792 {
17793 if($Debug) {
17794 printMsg("INFO", "running $Cmd");
17795 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017796 if($OSgroup ne "windows"
17797 and $OSgroup ne "macos")
17798 {
17799 if($Cmd!~/lynx|links/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017800 $Cmd .= " >\"/dev/null\" 2>&1 &";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017801 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017802 }
17803 system($Cmd);
17804 }
17805 else {
17806 printMsg("ERROR", "cannot open report in browser");
17807 }
17808}
17809
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017810sub getReport($)
17811{
17812 my $Level = $_[0];
17813 if($ReportFormat eq "xml")
17814 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017815 if($Level eq "Join")
17816 {
17817 my $Report = "<reports>\n";
17818 $Report .= getReport("Binary");
17819 $Report .= getReport("Source");
17820 $Report .= "</reports>\n";
17821 return $Report;
17822 }
17823 else
17824 {
17825 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17826 my ($Summary, $MetaData) = get_Summary($Level);
17827 $Report .= $Summary."\n";
17828 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17829 $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 +040017830
17831 # additional symbols info (if needed)
17832 # $Report .= get_Report_SymbolsInfo($Level);
17833
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017834 $Report .= "</report>\n";
17835 return $Report;
17836 }
17837 }
17838 else
17839 { # HTML
17840 my $CssStyles = readModule("Styles", "Report.css");
17841 my $JScripts = readModule("Scripts", "Sections.js");
17842 if($Level eq "Join")
17843 {
17844 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17845 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040017846 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
17847 my $Keywords = $TargetLibraryFName.", compatibility, API, report";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017848 my $Description = "Compatibility report for the $TargetLibraryFName $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
17849 my ($BSummary, $BMetaData) = get_Summary("Binary");
17850 my ($SSummary, $SMetaData) = get_Summary("Source");
17851 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>";
17852 $Report .= get_Report_Header("Join")."
17853 <br/><div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017854 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17855 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017856 </div>";
17857 $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>";
17858 $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 Ponomarenko9927e332012-10-19 10:50:48 +040017859 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017860 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
17861 return $Report;
17862 }
17863 else
17864 {
17865 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040017866 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17867 my $Keywords = $TargetLibraryFName.", ".lc($Level)." compatibility, API, report";
17868 my $Description = "$Level compatibility report for the ".$TargetLibraryFName." ".$TargetComponent." between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017869 if($Level eq "Binary")
17870 {
17871 if(getArch(1) eq getArch(2)
17872 and getArch(1) ne "unknown") {
17873 $Description .= " on ".showArch(getArch(1));
17874 }
17875 }
17876 my $Report = "<!-\- $MetaData -\->\n".composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."\n<body>\n<div><a name='Top'></a>\n";
17877 $Report .= get_Report_Header($Level)."\n".$Summary."\n";
17878 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17879 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17880 $Report .= get_SourceInfo();
17881 $Report .= "</div>\n<br/><br/><br/><hr/>\n";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017882 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017883 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
17884 return $Report;
17885 }
17886 }
17887}
17888
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017889sub getLegend()
17890{
17891 return "<br/>
17892<table class='summary'>
17893<tr>
17894 <td class='new'>added</td>
17895 <td class='passed'>compatible</td>
17896</tr>
17897<tr>
17898 <td class='warning'>warning</td>
17899 <td class='failed'>incompatible</td>
17900</tr></table>\n";
17901}
17902
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017903sub createReport()
17904{
17905 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017906 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017907 writeReport("Join", getReport("Join"));
17908 }
17909 elsif($DoubleReport)
17910 { # default
17911 writeReport("Binary", getReport("Binary"));
17912 writeReport("Source", getReport("Source"));
17913 }
17914 elsif($BinaryOnly)
17915 { # --binary
17916 writeReport("Binary", getReport("Binary"));
17917 }
17918 elsif($SourceOnly)
17919 { # --source
17920 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017921 }
17922}
17923
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017924sub getReportFooter($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017925{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017926 my ($LibName, $Wide) = @_;
17927 my $FooterStyle = $Wide?"width:99%":"width:97%;padding-top:3px";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017928 my $Footer = "<div style='$FooterStyle;font-size:11px;' align='right'><i>Generated on ".(localtime time); # report date
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017929 $Footer .= " for <span style='font-weight:bold'>$LibName</span>"; # tested library/system name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017930 $Footer .= " by <a href='".$HomePage{"Wiki"}."'>ABI Compliance Checker</a>"; # tool name
17931 my $ToolSummary = "<br/>A tool for checking backward compatibility of a C/C++ library API&#160;&#160;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017932 $Footer .= " $TOOL_VERSION &#160;$ToolSummary</i></div>"; # tool version
17933 return $Footer;
17934}
17935
17936sub get_Report_Problems($$)
17937{
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017938 my ($Severity, $Level) = @_;
17939 my $Report = get_Report_TypeProblems($Severity, $Level);
17940 if(my $SProblems = get_Report_SymbolProblems($Severity, $Level)) {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017941 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017942 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017943 if($Severity eq "Low")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017944 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017945 $Report .= get_Report_ChangedConstants("Low", $Level);
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +040017946 if($ReportFormat eq "html")
17947 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017948 if($CheckImpl and $Level eq "Binary") {
17949 $Report .= get_Report_Impl();
17950 }
17951 }
17952 }
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017953 if($Severity eq "Safe")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017954 {
17955 $Report .= get_Report_ChangedConstants("Safe", $Level);
17956 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017957 if($ReportFormat eq "html")
17958 {
17959 if($Report)
17960 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017961 if($JoinReport)
17962 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017963 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017964 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17965 }
17966 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017967 $Report = "<a name=\'".$Severity."_Risk_".$Level."_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017968 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017969 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017970 else
17971 {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017972 if($Severity eq "Safe") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017973 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17974 }
17975 else {
Andrey Ponomarenko2489ef82013-09-16 18:23:15 +040017976 $Report = "<a name=\'".$Severity."_Risk_Problems\'></a>".$Report;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017977 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017978 }
17979 }
17980 }
17981 return $Report;
17982}
17983
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017984sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017985{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017986 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17987 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17988 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17989 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017990 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17991 <meta name=\"keywords\" content=\"$Keywords\" />
17992 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017993 <title>
17994 $Title
17995 </title>
17996 <style type=\"text/css\">
17997 $Styles
17998 </style>
17999 <script type=\"text/javascript\" language=\"JavaScript\">
18000 <!--
18001 $Scripts
18002 -->
18003 </script>
18004 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018005}
18006
18007sub insertIDs($)
18008{
18009 my $Text = $_[0];
18010 while($Text=~/CONTENT_ID/)
18011 {
18012 if(int($Content_Counter)%2) {
18013 $ContentID -= 1;
18014 }
18015 $Text=~s/CONTENT_ID/c_$ContentID/;
18016 $ContentID += 1;
18017 $Content_Counter += 1;
18018 }
18019 return $Text;
18020}
18021
18022sub checkPreprocessedUnit($)
18023{
18024 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018025 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018026 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018027 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018028
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018029 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018030 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018031 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018032 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018033 chomp($Line);
18034 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018035 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018036 $CurHeader = path_format($1, $OSgroup);
18037 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018038 $CurClass = "";
18039
18040 if(index($CurHeader, $TMP_DIR)==0) {
18041 next;
18042 }
18043
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018044 if(substr($CurHeaderName, 0, 1) eq "<")
18045 { # <built-in>, <command-line>, etc.
18046 $CurHeaderName = "";
18047 $CurHeader = "";
18048 }
18049
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018050 if($ExtraInfo)
18051 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018052 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018053 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
18054 }
18055 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018056 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018057 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018058 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018059 if($CurHeaderName)
18060 {
18061 if(not $Include_Neighbors{$Version}{$CurHeaderName}
18062 and not $Registered_Headers{$Version}{$CurHeader})
18063 { # not a target
18064 next;
18065 }
18066 if(not is_target_header($CurHeaderName, 1)
18067 and not is_target_header($CurHeaderName, 2))
18068 { # user-defined header
18069 next;
18070 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018071 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018072 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018073
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018074 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018075 {
18076 my ($Name, $Value) = ($1, $2);
18077 if(not $Constants{$Version}{$Name}{"Access"})
18078 {
18079 $Constants{$Version}{$Name}{"Access"} = "public";
18080 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018081 if($CurHeaderName) {
18082 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
18083 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018084 }
18085 }
18086 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
18087 $Constants{$Version}{$1}{"Access"} = "private";
18088 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018089 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018090 else
18091 {
18092 if(defined $ExtraDump)
18093 {
18094 if($Line=~/(\w+)\s*\(/)
18095 { # functions
18096 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18097 }
18098 #elsif($Line=~/(\w+)\s*;/)
18099 #{ # data
18100 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
18101 #}
18102 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
18103 $CurClass = $2;
18104 }
18105 }
18106 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018107 }
18108 close(PREPROC);
18109 foreach my $Constant (keys(%{$Constants{$Version}}))
18110 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018111 if($Constants{$Version}{$Constant}{"Access"} eq "private")
18112 {
18113 delete($Constants{$Version}{$Constant});
18114 next;
18115 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040018116 if(not $ExtraDump and ($Constant=~/_h\Z/i
18117 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018118 { # skip
18119 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018120 }
18121 else {
18122 delete($Constants{$Version}{$Constant}{"Access"});
18123 }
18124 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018125 if($Debug)
18126 {
18127 mkpath($DEBUG_PATH{$Version});
18128 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
18129 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018130}
18131
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018132sub uncoverConstant($$)
18133{
18134 my ($LibVersion, $Constant) = @_;
18135 return "" if(not $LibVersion or not $Constant);
18136 return $Constant if(isCyclical(\@RecurConstant, $Constant));
18137 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
18138 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
18139 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018140
18141 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018142 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018143 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
18144 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018145 {
18146 push(@RecurConstant, $Constant);
18147 my $Uncovered = uncoverConstant($LibVersion, $Value);
18148 if($Uncovered ne "") {
18149 $Value = $Uncovered;
18150 }
18151 pop(@RecurConstant);
18152 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018153
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018154 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018155 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018156 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
18157 }
18158 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
18159}
18160
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018161sub simpleConstant($$)
18162{
18163 my ($LibVersion, $Value) = @_;
18164 if($Value=~/\W/)
18165 {
18166 my $Value_Copy = $Value;
18167 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
18168 {
18169 my $Word = $1;
18170 if($Value!~/$Word\s*\(/)
18171 {
18172 my $Val = uncoverConstant($LibVersion, $Word);
18173 if($Val ne "")
18174 {
18175 $Value=~s/\b$Word\b/$Val/g;
18176 }
18177 }
18178 }
18179 }
18180 return $Value;
18181}
18182
18183sub computeValue($)
18184{
18185 my $Value = $_[0];
18186
18187 if($Value=~/\A\((-?[\d]+)\)\Z/) {
18188 return $1;
18189 }
18190
18191 if($Value=~/\A[\d\-\+()]+\Z/) {
18192 return eval($Value);
18193 }
18194
18195 return $Value;
18196}
18197
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018198my %IgnoreConstant = map {$_=>1} (
18199 "VERSION",
18200 "VERSIONCODE",
18201 "VERNUM",
18202 "VERS_INFO",
18203 "PATCHLEVEL",
18204 "INSTALLPREFIX",
18205 "VBUILD",
18206 "VPATCH",
18207 "VMINOR",
18208 "BUILD_STRING",
18209 "BUILD_TIME",
18210 "PACKAGE_STRING",
18211 "PRODUCTION",
18212 "CONFIGURE_COMMAND",
18213 "INSTALLDIR",
18214 "BINDIR",
18215 "CONFIG_FILE_PATH",
18216 "DATADIR",
18217 "EXTENSION_DIR",
18218 "INCLUDE_PATH",
18219 "LIBDIR",
18220 "LOCALSTATEDIR",
18221 "SBINDIR",
18222 "SYSCONFDIR",
18223 "RELEASE",
18224 "SOURCE_ID",
18225 "SUBMINOR",
18226 "MINOR",
18227 "MINNOR",
18228 "MINORVERSION",
18229 "MAJOR",
18230 "MAJORVERSION",
18231 "MICRO",
18232 "MICROVERSION",
18233 "BINARY_AGE",
18234 "INTERFACE_AGE",
18235 "CORE_ABI",
18236 "PATCH",
18237 "COPYRIGHT",
18238 "TIMESTAMP",
18239 "REVISION",
18240 "PACKAGE_TAG",
18241 "PACKAGEDATE",
18242 "NUMVERSION",
18243 "Release",
18244 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018245);
18246
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018247sub constantFilter($$$)
18248{
18249 my ($Name, $Value, $Level) = @_;
18250
18251 if($Level eq "Binary")
18252 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018253 if($Name=~/_t\Z/)
18254 { # __malloc_ptr_t
18255 return 1;
18256 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018257 foreach (keys(%IgnoreConstant))
18258 {
18259 if($Name=~/(\A|_)$_(_|\Z)/)
18260 { # version
18261 return 1;
18262 }
18263 if(/\A[A-Z].*[a-z]\Z/)
18264 {
18265 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
18266 { # version
18267 return 1;
18268 }
18269 }
18270 }
18271 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
18272 { # version
18273 return 1;
18274 }
18275 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
18276 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
18277 return 1;
18278 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018279
18280 if($Value=~/\A["'].*['"]/i)
18281 { # string
18282 return 0;
18283 }
18284
18285 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
18286 { # static int gcry_pth_init
18287 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018288 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018289 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018290 return 1;
18291 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018292 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018293 { # foo(p)
18294 return 1;
18295 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018296 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018297 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018298 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018299 return 1;
18300 }
18301 }
18302
18303 return 0;
18304}
18305
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018306sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018307{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018308 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018309 foreach my $Constant (keys(%{$Constants{1}}))
18310 {
18311 if($SkipConstants{1}{$Constant})
18312 { # skipped by the user
18313 next;
18314 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018315
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018316 if(my $Header = $Constants{1}{$Constant}{"Header"})
18317 {
18318 if(not is_target_header($Header, 1)
18319 and not is_target_header($Header, 2))
18320 { # user-defined header
18321 next;
18322 }
18323 }
18324 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018325 next;
18326 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018327
18328 my $Old_Value = uncoverConstant(1, $Constant);
18329
18330 if(constantFilter($Constant, $Old_Value, $Level))
18331 { # separate binary and source problems
18332 next;
18333 }
18334
18335 if(not defined $Constants{2}{$Constant}{"Value"})
18336 { # removed
18337 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18338 "Target"=>$Constant,
18339 "Old_Value"=>$Old_Value );
18340 next;
18341 }
18342
18343 if($Constants{2}{$Constant}{"Value"} eq "")
18344 { # empty value
18345 # TODO: implement a rule
18346 next;
18347 }
18348
18349 my $New_Value = uncoverConstant(2, $Constant);
18350
18351 my $Old_Value_Pure = $Old_Value;
18352 my $New_Value_Pure = $New_Value;
18353
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018354 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18355 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18356 $New_Value_Pure=~s/(\W)\s+/$1/g;
18357 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018358
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018359 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018360
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018361 if($New_Value_Pure ne $Old_Value_Pure)
18362 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018363 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18364 { # complex values
18365 next;
18366 }
18367 if(computeValue($Old_Value) eq computeValue($New_Value))
18368 { # expressions
18369 next;
18370 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018371 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18372 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18373 next;
18374 }
18375 if($Old_Value eq "0" and $New_Value eq "NULL")
18376 { # 0 => NULL
18377 next;
18378 }
18379 if($Old_Value eq "NULL" and $New_Value eq "0")
18380 { # NULL => 0
18381 next;
18382 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018383 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018384 "Target"=>$Constant,
18385 "Old_Value"=>$Old_Value,
18386 "New_Value"=>$New_Value );
18387 }
18388 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018389
18390 foreach my $Constant (keys(%{$Constants{2}}))
18391 {
18392 if(not defined $Constants{1}{$Constant}{"Value"})
18393 {
18394 if($SkipConstants{2}{$Constant})
18395 { # skipped by the user
18396 next;
18397 }
18398
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018399 if(my $Header = $Constants{2}{$Constant}{"Header"})
18400 {
18401 if(not is_target_header($Header, 1)
18402 and not is_target_header($Header, 2))
18403 { # user-defined header
18404 next;
18405 }
18406 }
18407 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018408 next;
18409 }
18410
18411 my $New_Value = uncoverConstant(2, $Constant);
18412 if(not defined $New_Value or $New_Value eq "") {
18413 next;
18414 }
18415
18416 if(constantFilter($Constant, $New_Value, $Level))
18417 { # separate binary and source problems
18418 next;
18419 }
18420
18421 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18422 "Target"=>$Constant,
18423 "New_Value"=>$New_Value );
18424 }
18425 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018426}
18427
18428sub convert_integer($)
18429{
18430 my $Value = $_[0];
18431 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018432 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018433 return hex($Value);
18434 }
18435 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018436 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018437 return oct($Value);
18438 }
18439 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018440 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018441 return oct($Value);
18442 }
18443 else {
18444 return $Value;
18445 }
18446}
18447
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018448sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018449{
18450 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018451 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018452 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018453 {
18454 if($LibVersion==1)
18455 {
18456 printMsg("WARNING", "checking headers only");
18457 $CheckHeadersOnly = 1;
18458 }
18459 else {
18460 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18461 }
18462 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018463
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018464 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018465 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018466 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018467
18468 if($CheckUndefined)
18469 {
18470 my %UndefinedLibs = ();
18471
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018472 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18473
18474 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018475 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018476 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018477 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018478 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018479 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018480 if($Symbol_Library{$LibVersion}{$Symbol}
18481 or $DepSymbol_Library{$LibVersion}{$Symbol})
18482 { # exported by target library
18483 next;
18484 }
18485 if(index($Symbol, '@')!=-1)
18486 { # exported default symbol version (@@)
18487 $Symbol=~s/\@/\@\@/;
18488 if($Symbol_Library{$LibVersion}{$Symbol}
18489 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18490 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018491 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018492 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018493 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18494 $UndefinedLibs{$Path} = 1;
18495 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018496 }
18497 }
18498 }
18499 if($ExtraInfo)
18500 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018501 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018502 {
18503 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018504 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018505 foreach (@Paths)
18506 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018507 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018508 my ($Dir, $Name) = separate_path($_);
18509
18510 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018511 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018512 }
18513
18514 $Name = parse_libname($Name, "name", $OStarget);
18515 $Name=~s/\Alib//;
18516
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018517 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018518 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018519
18520 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18521 {
18522 $LibString = " -L".esc($Dir).$LibString;
18523 }
18524
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018525 writeFile($ExtraInfo."/libs-string", $LibString);
18526 }
18527 }
18528 }
18529
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018530 if($ExtraInfo) {
18531 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18532 }
18533
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018534 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018535 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018536 if($#LibPaths!=-1)
18537 {
18538 if(not keys(%{$Symbol_Library{$LibVersion}}))
18539 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018540 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018541 printMsg("WARNING", "checking headers only");
18542 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018543 }
18544 }
18545 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018546
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018547 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018548 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018549}
18550
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018551my %Prefix_Lib_Map=(
18552 # symbols for autodetecting library dependencies (by prefix)
18553 "pthread_" => ["libpthread"],
18554 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18555 "cairo_" => ["libcairo"],
18556 "gtk_" => ["libgtk-x11-2.0"],
18557 "atk_" => ["libatk-1.0"],
18558 "gdk_" => ["libgdk-x11-2.0"],
18559 "gl" => ["libGL"],
18560 "glu" => ["libGLU"],
18561 "popt" => ["libpopt"],
18562 "Py" => ["libpython"],
18563 "jpeg_" => ["libjpeg"],
18564 "BZ2_" => ["libbz2"],
18565 "Fc" => ["libfontconfig"],
18566 "Xft" => ["libXft"],
18567 "SSL_" => ["libssl"],
18568 "sem_" => ["libpthread"],
18569 "snd_" => ["libasound"],
18570 "art_" => ["libart_lgpl_2"],
18571 "dbus_g" => ["libdbus-glib-1"],
18572 "GOMP_" => ["libgomp"],
18573 "omp_" => ["libgomp"],
18574 "cms" => ["liblcms"]
18575);
18576
18577my %Pattern_Lib_Map=(
18578 "SL[a-z]" => ["libslang"]
18579);
18580
18581my %Symbol_Lib_Map=(
18582 # symbols for autodetecting library dependencies (by name)
18583 "pow" => "libm",
18584 "fmod" => "libm",
18585 "sin" => "libm",
18586 "floor" => "libm",
18587 "cos" => "libm",
18588 "dlopen" => "libdl",
18589 "deflate" => "libz",
18590 "inflate" => "libz",
18591 "move_panel" => "libpanel",
18592 "XOpenDisplay" => "libX11",
18593 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018594 "clock_gettime" => "librt",
18595 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018596);
18597
18598sub find_SymbolLibs($$)
18599{
18600 my ($LibVersion, $Symbol) = @_;
18601
18602 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18603 { # debug symbols
18604 return ();
18605 }
18606
18607 my %Paths = ();
18608
18609 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18610 {
18611 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18612 $Paths{$Path} = 1;
18613 }
18614 }
18615
18616 if(my $SymbolPrefix = getPrefix($Symbol))
18617 {
18618 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18619 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18620 }
18621
18622 if(not keys(%Paths))
18623 {
18624 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18625 {
18626 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18627 {
18628 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18629 $Paths{$Path} = 1;
18630 }
18631 }
18632 }
18633 }
18634
18635 if(not keys(%Paths))
18636 {
18637 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18638 {
18639 if($Symbol=~/\A$Prefix/)
18640 {
18641 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18642 {
18643 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18644 $Paths{$Path} = 1;
18645 }
18646 }
18647 }
18648 }
18649 }
18650
18651 if(not keys(%Paths))
18652 {
18653 if($SymbolPrefix)
18654 { # try to find a library by symbol prefix
18655 if($SymbolPrefix eq "inotify" and
18656 index($Symbol, "\@GLIBC")!=-1)
18657 {
18658 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18659 $Paths{$Path} = 1;
18660 }
18661 }
18662 else
18663 {
18664 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18665 $Paths{$Path} = 1;
18666 }
18667 }
18668 }
18669 }
18670
18671 if(my @Paths = keys(%Paths)) {
18672 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18673 }
18674 }
18675 return keys(%Paths);
18676}
18677
18678sub get_LibPath_Prefix($$)
18679{
18680 my ($LibVersion, $Prefix) = @_;
18681
18682 $Prefix = lc($Prefix);
18683 $Prefix=~s/[_]+\Z//g;
18684
18685 foreach ("-2", "2", "-1", "1", "")
18686 { # libgnome-2.so
18687 # libxml2.so
18688 # libdbus-1.so
18689 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18690 return $Path;
18691 }
18692 }
18693 return "";
18694}
18695
18696sub getPrefix($)
18697{
18698 my $Str = $_[0];
18699 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18700 { # XmuValidArea: Xmu
18701 return $1;
18702 }
18703 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18704 { # snfReadFont: snf
18705 return $1;
18706 }
18707 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18708 { # XRRTimes: XRR
18709 return $1;
18710 }
18711 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18712 { # H5HF_delete: H5
18713 return $1;
18714 }
18715 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18716 { # alarm_event_add: alarm_
18717 return $1;
18718 }
18719 elsif($Str=~/\A(([a-z])\2{1,})/i)
18720 { # ffopen
18721 return $1;
18722 }
18723 return "";
18724}
18725
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018726sub getSymbolSize($$)
18727{ # size from the shared library
18728 my ($Symbol, $LibVersion) = @_;
18729 return 0 if(not $Symbol);
18730 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18731 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18732 {
18733 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18734 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18735 {
18736 if($Size<0) {
18737 return -$Size;
18738 }
18739 }
18740 }
18741 return 0;
18742}
18743
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018744sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018745{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18746 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018747 my ($Name, $Type) = @_;
18748
18749 # single
18750 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018751 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018752 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018753 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018754 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018755
18756 # double
18757 if($Name=~/$DEFAULT_STD_PARMS/)
18758 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018759 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018760 {
18761 my ($ShortName, $FuncParams) = split_Signature($Name);
18762
18763 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18764 {
18765 if(index($FParam, "<")!=-1)
18766 {
18767 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18768 my $FParam_N = canonifyName($FParam, "T");
18769 if($FParam_N ne $FParam) {
18770 $Name=~s/\Q$FParam\E/$FParam_N/g;
18771 }
18772 }
18773 }
18774 }
18775 elsif($Type eq "T")
18776 {
18777 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18778
18779 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018780 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018781 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018782 my $FParam = $TParams[0];
18783 foreach my $Pos (1 .. $#TParams)
18784 {
18785 my $TParam = $TParams[$Pos];
18786 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18787 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18788 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018789 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018790 }
18791 }
18792 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018793 if($Type eq "S") {
18794 return formatName($Name, "S");
18795 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018796 return $Name;
18797}
18798
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018799sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018800{
18801 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018802 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018803 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018804 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018805 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018806 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018807 next if($tr_name{$Symbol});
18808 $Symbol=~s/[\@\$]+(.*)\Z//;
18809 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018810 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018811 elsif(index($Symbol, "?")==0)
18812 {
18813 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018814 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018815 }
18816 else
18817 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018818 $tr_name{$Symbol} = $Symbol;
18819 $mangled_name_gcc{$Symbol} = $Symbol;
18820 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018821 }
18822 }
18823 if($#MnglNames1 > -1)
18824 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018825 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018826 foreach my $MnglName (@MnglNames1)
18827 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018828 if(my $Unmangled = pop(@UnmangledNames))
18829 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018830 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018831 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18832 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18833 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018834 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018835 and $tr_name{$MnglName}=~/vtable for (.+)/)
18836 { # bind class name and v-table symbol
18837 my $ClassName = $1;
18838 $ClassVTable{$ClassName} = $MnglName;
18839 $VTableClass{$MnglName} = $ClassName;
18840 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018841 }
18842 }
18843 }
18844 if($#MnglNames2 > -1)
18845 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018846 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018847 foreach my $MnglName (@MnglNames2)
18848 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018849 if(my $Unmangled = pop(@UnmangledNames))
18850 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018851 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018852 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18853 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018854 }
18855 }
18856 return \%tr_name;
18857}
18858
18859sub link_symbol($$$)
18860{
18861 my ($Symbol, $RunWith, $Deps) = @_;
18862 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18863 return 1;
18864 }
18865 if($Deps eq "+Deps")
18866 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018867 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018868 return 1;
18869 }
18870 }
18871 return 0;
18872}
18873
18874sub link_symbol_internal($$$)
18875{
18876 my ($Symbol, $RunWith, $Where) = @_;
18877 return 0 if(not $Where or not $Symbol);
18878 if($Where->{$RunWith}{$Symbol})
18879 { # the exact match by symbol name
18880 return 1;
18881 }
18882 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18883 { # indirect symbol version, i.e.
18884 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018885 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018886 if($Where->{$RunWith}{$VSym}) {
18887 return 1;
18888 }
18889 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018890 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018891 if($Sym and $Ver)
18892 { # search for the symbol with the same version
18893 # or without version
18894 if($Where->{$RunWith}{$Sym})
18895 { # old: foo@v|foo@@v
18896 # new: foo
18897 return 1;
18898 }
18899 if($Where->{$RunWith}{$Sym."\@".$Ver})
18900 { # old: foo|foo@@v
18901 # new: foo@v
18902 return 1;
18903 }
18904 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18905 { # old: foo|foo@v
18906 # new: foo@@v
18907 return 1;
18908 }
18909 }
18910 return 0;
18911}
18912
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018913sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018914{
18915 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018916 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018917 my @Imported = ();
18918 if($OSgroup eq "macos")
18919 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018920 my $NM = get_CmdPath("nm");
18921 if(not $NM) {
18922 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018923 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018924 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018925 while(<APP>)
18926 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018927 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018928 push(@Imported, $1);
18929 }
18930 }
18931 close(APP);
18932 }
18933 elsif($OSgroup eq "windows")
18934 {
18935 my $DumpBinCmd = get_CmdPath("dumpbin");
18936 if(not $DumpBinCmd) {
18937 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18938 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018939 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018940 while(<APP>)
18941 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018942 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18943 push(@Imported, $1);
18944 }
18945 }
18946 close(APP);
18947 }
18948 else
18949 {
18950 my $ReadelfCmd = get_CmdPath("readelf");
18951 if(not $ReadelfCmd) {
18952 exitStatus("Not_Found", "can't find \"readelf\"");
18953 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040018954 open(APP, "$ReadelfCmd -Ws \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018955 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018956 while(<APP>)
18957 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018958 if(defined $symtab)
18959 { # do nothing with symtab
18960 if(index($_, "'.dynsym'")!=-1)
18961 { # dynamic table
18962 $symtab = undef;
18963 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018964 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018965 elsif(index($_, "'.symtab'")!=-1)
18966 { # symbol table
18967 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018968 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018969 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018970 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018971 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18972 if($Ndx eq "UND")
18973 { # only imported symbols
18974 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018975 }
18976 }
18977 }
18978 close(APP);
18979 }
18980 return @Imported;
18981}
18982
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018983my %ELF_BIND = map {$_=>1} (
18984 "WEAK",
18985 "GLOBAL"
18986);
18987
18988my %ELF_TYPE = map {$_=>1} (
18989 "FUNC",
18990 "IFUNC",
18991 "OBJECT",
18992 "COMMON"
18993);
18994
18995my %ELF_VIS = map {$_=>1} (
18996 "DEFAULT",
18997 "PROTECTED"
18998);
18999
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019000sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019001{ # read the line of 'readelf' output corresponding to the symbol
19002 my @Info = split(/\s+/, $_[0]);
19003 # Num: Value Size Type Bind Vis Ndx Name
19004 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019005 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019006 shift(@Info); # spaces
19007 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019008
19009 if($#Info==7)
19010 { # UND SYMBOL (N)
19011 if($Info[7]=~/\(\d+\)/) {
19012 pop(@Info);
19013 }
19014 }
19015
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019016 if($#Info!=6)
19017 { # other lines
19018 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019019 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019020 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019021 return () if(not defined $ELF_BIND{$Info[3]});
19022 return () if(not defined $ELF_VIS{$Info[4]});
19023 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
19024 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
19025 return ();
19026 }
19027 if($OStarget eq "symbian")
19028 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
19029 if(index($Info[6], "_._.absent_export_")!=-1)
19030 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
19031 return ();
19032 }
19033 $Info[6]=~s/\@.+//g; # remove version
19034 }
19035 if(index($Info[2], "0x") == 0)
19036 { # size == 0x3d158
19037 $Info[2] = hex($Info[2]);
19038 }
19039 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019040}
19041
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019042sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019043{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019044 my ($LibVersion, $Name) = @_;
19045 return "" if(not $LibVersion or not $Name);
19046 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
19047 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019048 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019049 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
19050}
19051
19052sub get_LibPath_I($$)
19053{
19054 my ($LibVersion, $Name) = @_;
19055 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019056 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019057 if(-f $Name)
19058 { # absolute path
19059 return $Name;
19060 }
19061 else
19062 { # broken
19063 return "";
19064 }
19065 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019066 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019067 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019068 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019069 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019070 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019071 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019072 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019073 }
19074 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
19075 { # ldconfig default paths
19076 return $DefaultPath;
19077 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019078 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019079 { # search in default linker directories
19080 # and then in all system paths
19081 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019082 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019083 }
19084 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019085 if(not defined $Cache{"checkSystemFiles"}) {
19086 checkSystemFiles();
19087 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019088 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
19089 return $AllObjects[0];
19090 }
19091 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
19092 {
19093 if($ShortName ne $Name)
19094 { # FIXME: check this case
19095 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
19096 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019097 }
19098 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019099 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019100 # can't find
19101 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019102}
19103
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019104sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019105{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019106 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
19107 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019108
19109 my $Real_Path = realpath($Lib_Path);
19110
19111 if(not $Real_Path)
19112 { # broken link
19113 return ();
19114 }
19115
19116 my $Lib_Name = get_filename($Real_Path);
19117
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019118 if($ExtraInfo)
19119 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019120 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019121 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019122 }
19123
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019124 if($IsNeededLib)
19125 {
19126 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
19127 return ();
19128 }
19129 }
19130 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019131 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019132
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019133 if($CheckImpl)
19134 {
19135 if(not $IsNeededLib) {
19136 getImplementations($LibVersion, $Lib_Path);
19137 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019138 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019139
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019140 push(@RecurLib, $Lib_Name);
19141 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019142 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
19143
19144 if(not $IsNeededLib)
19145 { # special cases: libstdc++ and libc
19146 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
19147 {
19148 if($ShortName eq "libstdc++")
19149 { # libstdc++.so.6
19150 $STDCXX_TESTING = 1;
19151 }
19152 elsif($ShortName eq "libc")
19153 { # libc-2.11.3.so
19154 $GLIBC_TESTING = 1;
19155 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019156 }
19157 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019158 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019159 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019160 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019161 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019162 mkpath(get_dirname($DebugPath));
19163 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019164 if($OStarget eq "macos")
19165 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019166 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019167 if(not $NM) {
19168 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019169 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019170 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019171 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019172 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019173 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019174 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019175 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019176 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019177 else
19178 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019179 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019180 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019181 while(<LIB>)
19182 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019183 if($CheckUndefined)
19184 {
19185 if(not $IsNeededLib)
19186 {
19187 if(/ U _([\w\$]+)\s*\Z/)
19188 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019189 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019190 next;
19191 }
19192 }
19193 }
19194
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019195 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019196 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019197 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019198 if($IsNeededLib)
19199 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019200 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019201 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019202 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19203 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019204 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019205 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019206 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019207 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019208 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19209 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019210 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19211 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019212 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019213 setLanguage($LibVersion, "C++");
19214 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019215 }
19216 if($CheckObjectsOnly
19217 and $LibVersion==1) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019218 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019219 }
19220 }
19221 }
19222 }
19223 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019224
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019225 if($Deps)
19226 {
19227 if($LIB_TYPE eq "dynamic")
19228 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019229
19230 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019231 if(not $OtoolCmd) {
19232 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019233 }
19234
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019235 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19236 while(<LIB>)
19237 {
19238 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
19239 and $1 ne $Lib_Path) {
19240 $NeededLib{$1} = 1;
19241 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019242 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019243 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019244 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019245 }
19246 }
19247 elsif($OStarget eq "windows")
19248 { # Windows *.dll, *.lib
19249 my $DumpBinCmd = get_CmdPath("dumpbin");
19250 if(not $DumpBinCmd) {
19251 exitStatus("Not_Found", "can't find \"dumpbin\"");
19252 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019253 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019254 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019255 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019256 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019257 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019258 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019259 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019260 else
19261 { # write to pipe
19262 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019263 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019264 while(<LIB>)
19265 { # 1197 4AC 0000A620 SetThreadStackGuarantee
19266 # 1198 4AD SetThreadToken (forwarded to ...)
19267 # 3368 _o2i_ECPublicKey
19268 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*\Z/i
19269 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
19270 or /\A\s*\d+\s+_([\w\?\@]+)\s*\Z/)
19271 { # dynamic, static and forwarded symbols
19272 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019273 if($IsNeededLib)
19274 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019275 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019276 {
19277 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
19278 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
19279 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019280 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019281 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019282 {
19283 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
19284 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019285 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19286 {
19287 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
19288 setLanguage($LibVersion, "C++");
19289 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019290 }
19291 if($CheckObjectsOnly
19292 and $LibVersion==1) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019293 $CheckedSymbols{"Binary"}{$realname} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019294 }
19295 }
19296 }
19297 }
19298 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019299
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019300 if($Deps)
19301 {
19302 if($LIB_TYPE eq "dynamic")
19303 { # dependencies
19304 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19305 while(<LIB>)
19306 {
19307 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19308 and $1 ne $Lib_Path) {
19309 $NeededLib{path_format($1, $OSgroup)} = 1;
19310 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019311 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019312 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019313 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019314 }
19315 }
19316 else
19317 { # Unix; *.so, *.a
19318 # Symbian: *.dso, *.lib
19319 my $ReadelfCmd = get_CmdPath("readelf");
19320 if(not $ReadelfCmd) {
19321 exitStatus("Not_Found", "can't find \"readelf\"");
19322 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019323 my $Cmd = $ReadelfCmd." -Ws \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019324 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019325 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019326 # write to file
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019327 system($Cmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019328 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019329 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019330 else
19331 { # write to pipe
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019332 open(LIB, $Cmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019333 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019334 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019335 while(<LIB>)
19336 {
19337 if($LIB_TYPE eq "dynamic")
19338 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019339 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019340 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019341 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019342 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019343 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019344 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019345 # do nothing with symtab
19346 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019347 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019348 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019349 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019350 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019351 next;
19352 }
19353 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019354 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019355 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019356 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019357 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019358 if($CheckUndefined)
19359 {
19360 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019361 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019362 }
19363 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019364 next;
19365 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019366 if($Bind eq "WEAK")
19367 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019368 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019369 if($Weak eq "-Weak")
19370 { # skip WEAK symbols
19371 next;
19372 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019373 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019374 my $Short = $Symbol;
19375 $Short=~s/\@.+//g;
19376 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019377 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019378 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19379 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019380 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019381 if($IsNeededLib)
19382 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019383 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019384 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019385 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19386 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019387 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019388 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019389 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019390 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019391 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19392 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19393 if($Vers)
19394 {
19395 if($LIB_EXT eq "so")
19396 { # value
19397 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19398 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19399 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019400 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019401 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19402 {
19403 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19404 setLanguage($LibVersion, "C++");
19405 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019406 }
19407 if($CheckObjectsOnly
19408 and $LibVersion==1) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019409 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019410 }
19411 }
19412 }
19413 }
19414 close(LIB);
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019415
19416 if($Deps and $LIB_TYPE eq "dynamic")
19417 { # dynamic library specifics
19418 $Cmd = $ReadelfCmd." -Wd \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19419 open(LIB, $Cmd." |");
19420
19421 while(<LIB>)
19422 {
19423 if(/NEEDED.+\[([^\[\]]+)\]/)
19424 { # dependencies:
19425 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19426 $NeededLib{$1} = 1;
19427 }
19428 }
19429
19430 close(LIB);
19431 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019432 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019433 if($Vers)
19434 {
19435 if(not $IsNeededLib and $LIB_EXT eq "so")
19436 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019437 my %Found = ();
19438
19439 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019440 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019441 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019442 next if(index($Symbol,"\@")==-1);
19443 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019444 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019445 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019446 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019447 if($Symbol_SameValue ne $Symbol
19448 and index($Symbol_SameValue,"\@")==-1)
19449 {
19450 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019451 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019452 last;
19453 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019454 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019455 }
19456 }
19457
19458 # default
19459 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19460 {
19461 next if(defined $Found{$Symbol});
19462 next if(index($Symbol,"\@\@")==-1);
19463
19464 if($Symbol=~/\A([^\@]*)\@\@/
19465 and not $SymVer{$LibVersion}{$1})
19466 {
19467 $SymVer{$LibVersion}{$1} = $Symbol;
19468 $Found{$Symbol} = 1;
19469 }
19470 }
19471
19472 # non-default
19473 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19474 {
19475 next if(defined $Found{$Symbol});
19476 next if(index($Symbol,"\@")==-1);
19477
19478 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19479 and not $SymVer{$LibVersion}{$1})
19480 {
19481 $SymVer{$LibVersion}{$1} = $Symbol;
19482 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019483 }
19484 }
19485 }
19486 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019487 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019488 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019489 foreach my $DyLib (sort keys(%NeededLib))
19490 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019491 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19492
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019493 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19494 {
19495 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19496 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19497 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019498 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019499 }
19500 }
19501 pop(@RecurLib);
19502 return $Library_Symbol{$LibVersion};
19503}
19504
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019505sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019506{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019507 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019508 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019509 return keys(%Prefixes);
19510}
19511
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019512sub get_prefixes_I($$)
19513{
19514 foreach my $P (@{$_[0]})
19515 {
19516 my @Parts = reverse(split(/[\/\\]+/, $P));
19517 my $Name = $Parts[0];
19518 foreach (1 .. $#Parts)
19519 {
19520 $_[1]->{$Name}{$P} = 1;
19521 last if($_>4 or $Parts[$_] eq "include");
19522 $Name = $Parts[$_].$SLASH.$Name;
19523 }
19524 }
19525}
19526
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019527sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019528{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019529 $Cache{"checkSystemFiles"} = 1;
19530
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019531 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019532
19533 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019534 {
19535 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019536
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040019537 my @Files = cmd_find($DevelPath,"f");
19538 foreach my $Link (cmd_find($DevelPath,"l"))
19539 { # add symbolic links
19540 if(-f $Link) {
19541 push(@Files, $Link);
19542 }
19543 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019544
19545 if(not $CheckObjectsOnly)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019546 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019547 # search for headers in /usr/lib
Andrey Ponomarenko13bb0332013-06-28 15:32:28 +040019548 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19549 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19550 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019551 }
19552
19553 # search for libraries in /usr/lib (including symbolic links)
19554 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19555 foreach my $Path (@Libs)
19556 {
19557 my $N = get_filename($Path);
19558 $SystemObjects{$N}{$Path} = 1;
19559 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019560 }
19561 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019562
19563 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019564 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019565 foreach my $DevelPath (@{$SystemPaths{"include"}})
19566 {
19567 next if(not -d $DevelPath);
19568 # search for all header files in the /usr/include
19569 # with or without extension (ncurses.h, QtCore, ...)
19570 push(@SysHeaders, cmd_find($DevelPath,"f"));
19571 foreach my $Link (cmd_find($DevelPath,"l"))
19572 { # add symbolic links
19573 if(-f $Link) {
19574 push(@SysHeaders, $Link);
19575 }
19576 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019577 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019578 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019579 }
19580}
19581
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019582sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019583{
19584 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019585 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019586 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19587 {
19588 if(not -e $Dest) {
19589 exitStatus("Access_Error", "can't access \'$Dest\'");
19590 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019591 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019592 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19593 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019594 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019595 }
19596 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019597 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019598}
19599
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019600sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019601{
19602 my ($Path, $LibVersion) = @_;
19603 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019604 my $Name = get_filename($Path);
19605 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019606 return 1;
19607 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019608 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019609 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19610 return 1;
19611 }
19612 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19613 {
19614 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19615 return 1;
19616 }
19617 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019618 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019619 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019620 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019621 return 1;
19622 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019623 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019624 return 1;
19625 }
19626 }
19627 return 0;
19628}
19629
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019630sub specificHeader($$)
19631{
19632 my ($Header, $Spec) = @_;
19633 my $Name = get_filename($Header);
19634
19635 if($Spec eq "windows")
19636 {# MS Windows
19637 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19638 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19639 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19640 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19641 my @Dirs = (
19642 "win32",
19643 "win64",
19644 "win",
19645 "windows",
19646 "msvcrt"
19647 ); # /gsf-win32/
19648 if(my $DIRs = join("|", @Dirs)) {
19649 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19650 }
19651 }
19652 elsif($Spec eq "macos")
19653 { # Mac OS
19654 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19655 }
19656
19657 return 0;
19658}
19659
19660sub skipAlienHeader($)
19661{
19662 my $Path = $_[0];
19663 my $Name = get_filename($Path);
19664 my $Dir = get_dirname($Path);
19665
19666 if($Tolerance=~/2/)
19667 { # 2 - skip internal headers
19668 my @Terms = (
19669 "p",
19670 "priv",
19671 "int",
19672 "impl",
19673 "implementation",
19674 "internal",
19675 "private",
19676 "old",
19677 "compat",
19678 "debug",
19679 "test",
19680 "gen"
19681 );
19682
19683 my @Dirs = (
19684 "private",
19685 "priv",
19686 "port",
19687 "impl",
19688 "internal",
19689 "detail",
19690 "details",
19691 "old",
19692 "compat",
19693 "debug",
19694 "config",
19695 "compiler",
19696 "platform",
19697 "test"
19698 );
19699
19700 if(my $TERMs = join("|", @Terms)) {
19701 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19702 }
19703 if(my $DIRs = join("|", @Dirs)) {
19704 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19705 }
19706
19707 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19708 }
19709
19710 if($Tolerance=~/1/)
19711 { # 1 - skip non-Linux headers
19712 if($OSgroup ne "windows")
19713 {
19714 if(specificHeader($Path, "windows")) {
19715 return 1;
19716 }
19717 }
19718 if($OSgroup ne "macos")
19719 {
19720 if(specificHeader($Path, "macos")) {
19721 return 1;
19722 }
19723 }
19724 }
19725
19726 # valid
19727 return 0;
19728}
19729
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019730sub skipHeader($$)
19731{
19732 my ($Path, $LibVersion) = @_;
19733 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019734 if(defined $Cache{"skipHeader"}{$Path}) {
19735 return $Cache{"skipHeader"}{$Path};
19736 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019737 if(defined $Tolerance and $Tolerance=~/1|2/)
19738 { # --tolerant
19739 if(skipAlienHeader($Path)) {
19740 return ($Cache{"skipHeader"}{$Path} = 1);
19741 }
19742 }
19743 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19744 return 0;
19745 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019746 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19747}
19748
19749sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019750{ # returns:
19751 # 1 - if header should NOT be included and checked
19752 # 2 - if header should NOT be included, but should be checked
19753 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019754 my $Name = get_filename($Path);
19755 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019756 return $Kind;
19757 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019758 foreach my $D (sort {$SkipHeaders{$LibVersion}{"Path"}{$a} cmp $SkipHeaders{$LibVersion}{"Path"}{$b}}
19759 keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019760 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019761 if(index($Path, $D)!=-1)
19762 {
19763 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19764 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19765 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019766 }
19767 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040019768 foreach my $P (sort {$SkipHeaders{$LibVersion}{"Pattern"}{$a} cmp $SkipHeaders{$LibVersion}{"Pattern"}{$b}}
19769 keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019770 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019771 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19772 {
19773 if($Name=~/$P/) {
19774 return $Kind;
19775 }
19776 if($P=~/[\/\\]/ and $Path=~/$P/) {
19777 return $Kind;
19778 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019779 }
19780 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019781
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019782 return 0;
19783}
19784
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019785sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019786{
19787 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019788 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019789 { # system directory
19790 return;
19791 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019792 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019793 { # already registered
19794 return;
19795 }
19796 foreach my $Path (find_libs($Dir,"",1))
19797 {
19798 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019799 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019800 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019801 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019802 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19803}
19804
19805sub registerObject($$)
19806{
19807 my ($Path, $LibVersion) = @_;
19808 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019809 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019810 if($OSgroup=~/linux|bsd/i)
19811 {
19812 if(my $SONAME = getSONAME($Path)) {
19813 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19814 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019815 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019816 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19817 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019818 }
19819}
19820
19821sub getSONAME($)
19822{
19823 my $Path = $_[0];
19824 return if(not $Path);
19825 if(defined $Cache{"getSONAME"}{$Path}) {
19826 return $Cache{"getSONAME"}{$Path};
19827 }
19828 my $ObjdumpCmd = get_CmdPath("objdump");
19829 if(not $ObjdumpCmd) {
19830 exitStatus("Not_Found", "can't find \"objdump\"");
19831 }
Lénaïc Huarda914cb52014-02-06 15:55:02 +010019832 my $SonameCmd = "$ObjdumpCmd -x \"$Path\" 2>$TMP_DIR/null";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019833 if($OSgroup eq "windows") {
19834 $SonameCmd .= " | find \"SONAME\"";
19835 }
19836 else {
19837 $SonameCmd .= " | grep SONAME";
19838 }
19839 if(my $SonameInfo = `$SonameCmd`) {
19840 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19841 return ($Cache{"getSONAME"}{$Path} = $1);
19842 }
19843 }
19844 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019845}
19846
19847sub getSOPaths_Dest($$)
19848{
19849 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019850 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019851 return ();
19852 }
19853 if(-f $Dest)
19854 {
19855 if(not parse_libname($Dest, "name", $OStarget)) {
19856 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19857 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019858 registerObject($Dest, $LibVersion);
19859 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019860 return ($Dest);
19861 }
19862 elsif(-d $Dest)
19863 {
19864 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019865 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019866 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019867 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19868 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019869 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019870 { # all files and symlinks that match the name of a library
19871 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19872 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019873 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019874 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019875 }
19876 }
19877 }
19878 else
19879 { # search for all files and symlinks
19880 foreach my $Path (find_libs($Dest,"",""))
19881 {
19882 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019883 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019884 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019885 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019886 }
19887 if($OSgroup eq "macos")
19888 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019889 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019890 {
19891 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019892 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019893 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019894 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19895 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019896 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019897 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019898 }
19899 }
19900 }
19901 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019902 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019903 }
19904 else {
19905 return ();
19906 }
19907}
19908
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019909sub isCyclical($$)
19910{
19911 my ($Stack, $Value) = @_;
19912 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019913}
19914
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019915sub detectWordSize()
19916{
19917 return "" if(not $GCC_PATH);
19918 if($Cache{"detectWordSize"}) {
19919 return $Cache{"detectWordSize"};
19920 }
19921 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019922 my $Defines = `$GCC_PATH -E -dD \"$TMP_DIR/empty.h\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019923 unlink("$TMP_DIR/empty.h");
19924 my $WSize = 0;
19925 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019926 { # GCC 4
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019927 $WSize = $1;
19928 }
19929 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019930 { # GCC 3
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019931 my $PTRDIFF = $1;
19932 if($PTRDIFF=~/long/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019933 $WSize = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019934 }
19935 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019936 $WSize = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019937 }
19938 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019939 if(not $WSize) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019940 exitStatus("Error", "can't check WORD size");
19941 }
19942 return ($Cache{"detectWordSize"} = $WSize);
19943}
19944
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019945sub getWordSize($) {
19946 return $WORD_SIZE{$_[0]};
19947}
19948
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019949sub majorVersion($)
19950{
19951 my $V = $_[0];
19952 return 0 if(not $V);
19953 my @VParts = split(/\./, $V);
19954 return $VParts[0];
19955}
19956
19957sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019958{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019959 my ($V1, $V2) = @_;
19960 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019961 my @V1Parts = split(/\./, $V1);
19962 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019963 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
19964 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019965 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
19966 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
19967 }
19968 return -1 if($#V1Parts < $#V2Parts);
19969 return 1 if($#V1Parts > $#V2Parts);
19970 return 0;
19971}
19972
19973sub read_ABI_Dump($$)
19974{
19975 my ($LibVersion, $Path) = @_;
19976 return if(not $LibVersion or not -e $Path);
19977 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019978 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019979 { # input *.abi
19980 $FilePath = $Path;
19981 }
19982 else
19983 { # input *.abi.tar.gz
19984 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019985 if(not isDump_U($FilePath)) {
19986 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19987 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019988 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019989
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019990 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019991
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019992 my $Line = readLineNum($FilePath, 0);
19993 if($Line=~/xml/)
19994 { # XML format
19995 loadModule("XmlDump");
19996 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019997 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019998 else
19999 { # Perl Data::Dumper format (default)
20000 open(DUMP, $FilePath);
20001 local $/ = undef;
20002 my $Content = <DUMP>;
20003 close(DUMP);
20004
20005 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
20006 { # remove temp file
20007 unlink($FilePath);
20008 }
20009 if($Content!~/};\s*\Z/) {
20010 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
20011 }
20012 $ABI = eval($Content);
20013 if(not $ABI) {
20014 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
20015 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020016 }
20017 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020018 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020019 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020020 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020021 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020022 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020023 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020024 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020025
20026 if($ABI->{"ABI_DUMP_VERSION"})
20027 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020028 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020029 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020030 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020031 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020032 }
20033 else
20034 { # support for old ABI dumps
20035 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020036 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020037 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020038 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020039 }
20040 if(majorVersion($DVersion)<2)
20041 { # support for old ABI dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020042 if($UseOldDumps)
20043 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020044 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)<0) {
20045 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (older than $OLDEST_SUPPORTED_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020046 }
20047 }
20048 else
20049 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020050 my $Msg = "incompatible version \'$DVersion\' of specified ABI dump (allowed only 2.0<=V<=$ABI_DUMP_VERSION)";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020051 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)>=0) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020052 $Msg .= "\nUse -old-dumps option to use old-version dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020053 }
20054 exitStatus("Dump_Version", $Msg);
20055 }
20056 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020057
20058 if(defined $ABI->{"ABI_DUMPER_VERSION"})
20059 { # DWARF ABI Dump
20060 $UseConv_Real{$LibVersion}{"P"} = 1;
20061 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
20062
20063 $UsedDump{$LibVersion}{"DWARF"} = 1;
20064
20065 $TargetComponent = "module";
20066 }
20067
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020068 if(not checkDump($LibVersion, "2.11"))
20069 { # old ABI dumps
20070 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020071 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020072 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020073 { # ABI dump created with --binary option
20074 $UsedDump{$LibVersion}{"BinOnly"} = 1;
20075 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020076 else
20077 { # default
20078 $UsedDump{$LibVersion}{"SrcBin"} = 1;
20079 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020080
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020081 if(defined $ABI->{"Mode"}
20082 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020083 { # --ext option
20084 $ExtendedCheck = 1;
20085 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020086 if($ABI->{"Extra"}) {
20087 $ExtraDump = 1;
20088 }
20089
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020090 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020091 {
20092 $UsedDump{$LibVersion}{"L"} = $Lang;
20093 setLanguage($LibVersion, $Lang);
20094 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020095 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020096 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020097 }
20098 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020099 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020100 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020101 if(not $TInfo)
20102 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020103 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020104 }
20105 my %Tid_TDid = ();
20106 foreach my $TDid (keys(%{$TInfo}))
20107 {
20108 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
20109 {
20110 $MAX_ID = $Tid if($Tid>$MAX_ID);
20111 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020112 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020113 }
20114 }
20115 my %NewID = ();
20116 foreach my $Tid (keys(%Tid_TDid))
20117 {
20118 my @TDids = keys(%{$Tid_TDid{$Tid}});
20119 if($#TDids>=1)
20120 {
20121 foreach my $TDid (@TDids)
20122 {
20123 if($TDid) {
20124 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20125 }
20126 else
20127 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020128 my $ID = ++$MAX_ID;
20129
20130 $NewID{$TDid}{$Tid} = $ID;
20131 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
20132 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020133 }
20134 }
20135 }
20136 else
20137 {
20138 my $TDid = $TDids[0];
20139 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
20140 }
20141 }
20142 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
20143 {
20144 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
20145 if(defined $Info{"BaseType"})
20146 {
20147 my $Bid = $Info{"BaseType"}{"Tid"};
20148 my $BDid = $Info{"BaseType"}{"TDid"};
20149 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020150 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020151 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
20152 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
20153 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020154 }
20155 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
20156 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020157 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020158 read_Machine_DumpInfo($ABI, $LibVersion);
20159 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020160 if(not $SymbolInfo{$LibVersion})
20161 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020162 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020163 }
20164 if(not keys(%{$SymbolInfo{$LibVersion}}))
20165 { # validation of old-version dumps
20166 if(not $ExtendedCheck) {
20167 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
20168 }
20169 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020170 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020171 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020172 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020173 else
20174 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020175 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020176 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020177 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020178 }
20179 if(not $DepSymbols)
20180 { # Cannot reconstruct DepSymbols. This may result in false
20181 # positives if the old dump is for library 2. Not a problem if
20182 # old dumps are only from old libraries.
20183 $DepSymbols = {};
20184 }
20185 foreach my $Symbol (keys(%{$DepSymbols})) {
20186 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
20187 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020188 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020189 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020190
20191 if(my $V = $TargetVersion{$LibVersion}) {
20192 $Descriptor{$LibVersion}{"Version"} = $V;
20193 }
20194 else {
20195 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
20196 }
20197
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020198 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020199 if(not $SkipTypes{$LibVersion})
20200 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020201 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020202 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020203 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020204 if(not $SkipSymbols{$LibVersion})
20205 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020206 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020207 }
20208 if(not $SkipSymbols{$LibVersion})
20209 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020210 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020211 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020212 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
20213 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
20214 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020215 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020216 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020217 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020218 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020219 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020220 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020221 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020222 if(not checkDump($LibVersion, "2.10.1")
20223 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020224 { # support for old ABI dumps: added target headers
20225 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020226 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020227 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020228 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020229 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020230 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020231 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020232 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020233 if(defined $ABI->{"GccConstants"})
20234 { # 3.0
20235 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
20236 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
20237 }
20238 }
20239
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020240 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020241 if(not $NestedNameSpaces{$LibVersion})
20242 { # support for old dumps
20243 # Cannot reconstruct NameSpaces. This may affect design
20244 # of the compatibility report.
20245 $NestedNameSpaces{$LibVersion} = {};
20246 }
20247 # target system type
20248 # needed to adopt HTML report
20249 if(not $DumpSystem)
20250 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020251 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020252 }
20253 # recreate environment
20254 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
20255 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020256 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020257 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020258 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20259 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020260 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020261 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020262 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020263 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
20264 {
20265 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
20266 setLanguage($LibVersion, "C++");
20267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020268 }
20269 }
20270 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020271 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
20272 {
20273 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
20274 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
20275 }
20276 }
20277
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020278 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020279 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020280 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020281 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020282 {
20283 if(not $Symbol_Library{$LibVersion}{$MnglName}
20284 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
20285 push(@VFunc, $MnglName);
20286 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020287 }
20288 }
20289 translateSymbols(@VFunc, $LibVersion);
20290 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020291 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
20292
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020293 if(not checkDump($LibVersion, "3.0"))
20294 { # support for old ABI dumps
20295 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20296 {
20297 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
20298 {
20299 if(ref($BaseType) eq "HASH") {
20300 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
20301 }
20302 }
20303 }
20304 }
20305
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020306 if(not checkDump($LibVersion, "3.2"))
20307 { # support for old ABI dumps
20308 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20309 {
20310 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
20311 {
20312 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
20313 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
20314 }
20315 }
20316 }
20317
20318 # repair target headers list
20319 delete($TargetHeaders{$LibVersion});
20320 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020321 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20322 }
20323 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20324 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020325 }
20326
20327 # non-target constants from anon enums
20328 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20329 {
20330 if(not $ExtraDump
20331 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20332 {
20333 delete($Constants{$LibVersion}{$Name});
20334 }
20335 }
20336 }
20337
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020338 if(not checkDump($LibVersion, "2.20"))
20339 { # support for old ABI dumps
20340 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20341 {
20342 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20343
20344 if($TType=~/Struct|Union|Enum|Typedef/)
20345 { # repair complex types first
20346 next;
20347 }
20348
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020349 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020350 {
20351 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20352 if($BType=~/Struct|Union|Enum/i)
20353 {
20354 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20355 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20356 }
20357 }
20358 }
20359 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20360 {
20361 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20362 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20363 if($TType=~/Struct|Union|Enum/) {
20364 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20365 }
20366 }
20367 }
20368
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020369 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020370 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020371 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20372 { # support for old ABI dumps < 2.0 (ACC 1.22)
20373 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20374 {
20375 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20376 {
20377 if($Access ne "public") {
20378 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20379 }
20380 }
20381 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20382 }
20383 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20384 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020385 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20386 { # support for old ABI dumps
20387 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20388 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020389 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20390 { # DWARF ABI Dumps
20391 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20392 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020393 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20394 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20395 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020396 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20397 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020398 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020399 foreach (keys(%{$TInfo{"Base"}})) {
20400 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020401 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020402 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020403 if($TInfo{"Type"} eq "MethodPtr")
20404 {
20405 if(defined $TInfo{"Param"})
20406 { # support for old ABI dumps <= 1.17
20407 if(not defined $TInfo{"Param"}{"0"})
20408 {
20409 my $Max = keys(%{$TInfo{"Param"}});
20410 foreach my $Pos (1 .. $Max) {
20411 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20412 }
20413 delete($TInfo{"Param"}{$Max});
20414 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20415 }
20416 }
20417 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020418 if($TInfo{"BaseType"} eq $TypeId)
20419 { # fix ABI dump
20420 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20421 }
20422 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020423 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020424 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020425 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020426 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20427 if(not $BName)
20428 { # broken type
20429 next;
20430 }
20431 if($TInfo{"Name"} eq $BName)
20432 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020433 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020434 next;
20435 }
20436 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20437 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020438 }
20439 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020440 }
20441 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20442 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020443 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020444 }
20445 }
20446
20447 if(not checkDump($LibVersion, "2.15"))
20448 { # support for old ABI dumps
20449 my %Dups = ();
20450 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20451 {
20452 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020453 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020454 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20455 { # remove template decls
20456 delete($SymbolInfo{$LibVersion}{$InfoId});
20457 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020458 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020459 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020460 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20461 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020462 { # templates
20463 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020464 }
20465 }
20466 }
20467
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020468 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20469 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020470 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20471 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20472 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20473 { # support for old ABI dumps (< 3.1)
20474 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20475 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20476 { # add "this" first parameter
20477 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20478 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20479
20480 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20481 {
20482 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20483 foreach my $Pos (reverse(0 .. $#Pos)) {
20484 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20485 }
20486 }
20487 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20488 }
20489 }
20490
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020491 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20492 { # ABI dumps have no mangled names for C-functions
20493 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20494 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020495 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20496 { # support for old ABI dumps
20497 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20498 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020499 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20500 { # DWARF ABI Dumps
20501 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20502 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020503 }
20504
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020505 $Descriptor{$LibVersion}{"Dump"} = 1;
20506}
20507
20508sub read_Machine_DumpInfo($$)
20509{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020510 my ($ABI, $LibVersion) = @_;
20511 if($ABI->{"Arch"}) {
20512 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020513 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020514 if($ABI->{"WordSize"}) {
20515 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020516 }
20517 else
20518 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020519 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020520 }
20521 if(not $WORD_SIZE{$LibVersion})
20522 { # support for old dumps (<1.23)
20523 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20524 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020525 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020526 }
20527 else
20528 {
20529 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020530 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020531 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020532 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20533 { # any "pointer"-type
20534 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020535 last;
20536 }
20537 }
20538 if($PSize)
20539 { # a pointer type size
20540 $WORD_SIZE{$LibVersion} = $PSize;
20541 }
20542 else {
20543 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20544 }
20545 }
20546 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020547 if($ABI->{"GccVersion"}) {
20548 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020549 }
20550}
20551
20552sub read_Libs_DumpInfo($$)
20553{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020554 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020555 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20556 if(not $Library_Symbol{$LibVersion})
20557 { # support for old dumps
20558 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20559 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020560 if(keys(%{$Library_Symbol{$LibVersion}})
20561 and not $DumpAPI) {
20562 $Descriptor{$LibVersion}{"Libs"} = "OK";
20563 }
20564}
20565
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020566sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020567{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020568 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020569
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020570 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020571 and not $DumpAPI) {
20572 $Descriptor{$LibVersion}{"Headers"} = "OK";
20573 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020574 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020575 { # headers info is stored in the old dumps in the different way
20576 if($UseOldDumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020577 and my $Name = $ABI->{"Headers"}{$Identity}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020578 { # support for old dumps: headers info corrected in 1.22
20579 $Identity = $Name;
20580 }
20581 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020582 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020583 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020584
20585 if(keys(%{$ABI->{"Sources"}})
20586 and not $DumpAPI) {
20587 $Descriptor{$LibVersion}{"Sources"} = "OK";
20588 }
20589 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
20590 { # headers info is stored in the old dumps in the different way
20591 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20592 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20593 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020594}
20595
20596sub find_libs($$$)
20597{
20598 my ($Path, $Type, $MaxDepth) = @_;
20599 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020600 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020601}
20602
20603sub createDescriptor($$)
20604{
20605 my ($LibVersion, $Path) = @_;
20606 if(not $LibVersion or not $Path
20607 or not -e $Path) {
20608 return "";
20609 }
20610 if(-d $Path)
20611 { # directory with headers files and shared objects
20612 return "
20613 <version>
20614 ".$TargetVersion{$LibVersion}."
20615 </version>
20616
20617 <headers>
20618 $Path
20619 </headers>
20620
20621 <libs>
20622 $Path
20623 </libs>";
20624 }
20625 else
20626 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020627 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020628 { # standard XML-descriptor
20629 return readFile($Path);
20630 }
20631 elsif(is_header($Path, 2, $LibVersion))
20632 { # header file
20633 return "
20634 <version>
20635 ".$TargetVersion{$LibVersion}."
20636 </version>
20637
20638 <headers>
20639 $Path
20640 </headers>
20641
20642 <libs>
20643 none
20644 </libs>";
20645 }
20646 elsif(parse_libname($Path, "name", $OStarget))
20647 { # shared object
20648 return "
20649 <version>
20650 ".$TargetVersion{$LibVersion}."
20651 </version>
20652
20653 <headers>
20654 none
20655 </headers>
20656
20657 <libs>
20658 $Path
20659 </libs>";
20660 }
20661 else
20662 { # standard XML-descriptor
20663 return readFile($Path);
20664 }
20665 }
20666}
20667
20668sub detect_lib_default_paths()
20669{
20670 my %LPaths = ();
20671 if($OSgroup eq "bsd")
20672 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020673 if(my $LdConfig = get_CmdPath("ldconfig"))
20674 {
20675 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20676 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020677 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20678 {
20679 my $Name = "lib".$1;
20680 if(not defined $LPaths{$Name}) {
20681 $LPaths{$Name} = $2;
20682 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020683 }
20684 }
20685 }
20686 else {
20687 printMsg("WARNING", "can't find ldconfig");
20688 }
20689 }
20690 else
20691 {
20692 if(my $LdConfig = get_CmdPath("ldconfig"))
20693 {
20694 if($SystemRoot and $OSgroup eq "linux")
20695 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20696 if(-e $SystemRoot."/etc/ld.so.conf") {
20697 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20698 }
20699 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020700 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20701 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020702 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20703 {
20704 my ($Name, $Path) = ($1, $2);
20705 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020706 if(not defined $LPaths{$Name})
20707 { # get first element from the list of available paths
20708
20709 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20710 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20711 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20712
20713 $LPaths{$Name} = $Path;
20714 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020715 }
20716 }
20717 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020718 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020719 printMsg("WARNING", "can't find ldconfig");
20720 }
20721 }
20722 return \%LPaths;
20723}
20724
20725sub detect_bin_default_paths()
20726{
20727 my $EnvPaths = $ENV{"PATH"};
20728 if($OSgroup eq "beos") {
20729 $EnvPaths.=":".$ENV{"BETOOLS"};
20730 }
20731 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020732 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020733 {
20734 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020735 next if(not $Path);
20736 if($SystemRoot
20737 and $Path=~/\A\Q$SystemRoot\E\//)
20738 { # do NOT use binaries from target system
20739 next;
20740 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020741 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020742 }
20743}
20744
20745sub detect_inc_default_paths()
20746{
20747 return () if(not $GCC_PATH);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020748 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020749 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020750 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020751 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020752 next if(index($Line, "/cc1plus ")!=-1);
20753
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020754 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20755 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020756 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020757 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020758 if(index($Path, "c++")!=-1
20759 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020760 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020761 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020762 if(not defined $MAIN_CPP_DIR
20763 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20764 $MAIN_CPP_DIR = $Path;
20765 }
20766 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020767 elsif(index($Path, "gcc")!=-1) {
20768 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020769 }
20770 else
20771 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020772 if($Path=~/local[\/\\]+include/)
20773 { # local paths
20774 next;
20775 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020776 if($SystemRoot
20777 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20778 { # The GCC include path for user headers is not a part of the system root
20779 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20780 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20781 next;
20782 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020783 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020784 }
20785 }
20786 }
20787 unlink("$TMP_DIR/empty.h");
20788 return %DPaths;
20789}
20790
20791sub detect_default_paths($)
20792{
20793 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20794 my $Search = $_[0];
20795 if($Search!~/inc/) {
20796 $HSearch = 0;
20797 }
20798 if($Search!~/lib/) {
20799 $LSearch = 0;
20800 }
20801 if($Search!~/bin/) {
20802 $BSearch = 0;
20803 }
20804 if($Search!~/gcc/) {
20805 $GSearch = 0;
20806 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020807 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020808 { # <search_headers> section of the XML descriptor
20809 # do NOT search for systems headers
20810 $HSearch = 0;
20811 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020812 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020813 { # <search_headers> section of the XML descriptor
20814 # do NOT search for systems headers
20815 $LSearch = 0;
20816 }
20817 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20818 { # additional search paths
20819 next if($Type eq "include" and not $HSearch);
20820 next if($Type eq "lib" and not $LSearch);
20821 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020822 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020823 }
20824 if($OSgroup ne "windows")
20825 { # unix-like
20826 foreach my $Type ("include", "lib", "bin")
20827 { # automatic detection of system "devel" directories
20828 next if($Type eq "include" and not $HSearch);
20829 next if($Type eq "lib" and not $LSearch);
20830 next if($Type eq "bin" and not $BSearch);
20831 my ($UsrDir, $RootDir) = ("/usr", "/");
20832 if($SystemRoot and $Type ne "bin")
20833 { # 1. search for target headers and libraries
20834 # 2. use host commands: ldconfig, readelf, etc.
20835 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20836 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020837 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020838 if(-d $RootDir."/".$Type)
20839 { # if "/lib" is symbolic link
20840 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020841 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020842 }
20843 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020844 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020845 }
20846 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020847 if(-d $UsrDir)
20848 {
20849 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020850 if(-d $UsrDir."/".$Type)
20851 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020852 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020853 }
20854 }
20855 }
20856 }
20857 if($BSearch)
20858 {
20859 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020860 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020861 }
20862 # check environment variables
20863 if($OSgroup eq "beos")
20864 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020865 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020866 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020867 if($_ eq ".") {
20868 next;
20869 }
20870 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20871 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20872 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020873 }
20874 }
20875 if($HSearch)
20876 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020877 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20878 split(/:|;/, $ENV{"BEINCLUDES"})
20879 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020880 }
20881 if($LSearch)
20882 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020883 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20884 split(/:|;/, $ENV{"BELIBRARIES"}),
20885 split(/:|;/, $ENV{"LIBRARY_PATH"})
20886 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020887 }
20888 }
20889 if($LSearch)
20890 { # using linker to get system paths
20891 if(my $LPaths = detect_lib_default_paths())
20892 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020893 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020894 foreach my $Name (keys(%{$LPaths}))
20895 {
20896 if($SystemRoot
20897 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20898 { # wrong ldconfig configuration
20899 # check your <sysroot>/etc/ld.so.conf
20900 next;
20901 }
20902 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020903 if(my $Dir = get_dirname($LPaths->{$Name})) {
20904 $Dirs{$Dir} = 1;
20905 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020906 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020907 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020908 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020909 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020910 }
20911 if($BSearch)
20912 {
20913 if($CrossGcc)
20914 { # --cross-gcc=arm-linux-gcc
20915 if(-e $CrossGcc)
20916 { # absolute or relative path
20917 $GCC_PATH = get_abs_path($CrossGcc);
20918 }
20919 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20920 { # command name
20921 $GCC_PATH = $CrossGcc;
20922 }
20923 else {
20924 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20925 }
20926 if($GCC_PATH=~/\s/) {
20927 $GCC_PATH = "\"".$GCC_PATH."\"";
20928 }
20929 }
20930 }
20931 if($GSearch)
20932 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020933 if(not $CrossGcc)
20934 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020935 $GCC_PATH = get_CmdPath("gcc");
20936 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020937 if(not $GCC_PATH)
20938 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020939 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020940 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020941 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020942 { # select the latest version
20943 @GCCs = sort {$b cmp $a} @GCCs;
20944 if(check_gcc($GCCs[0], "3"))
20945 {
20946 $GCC_PATH = $GCCs[0];
20947 last;
20948 }
20949 }
20950 }
20951 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020952 if(not $GCC_PATH) {
20953 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
20954 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020955
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020956 if(not $CheckObjectsOnly_Opt)
20957 {
20958 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
20959 {
20960 my $GccTarget = get_dumpmachine($GCC_PATH);
20961 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget)");
20962 if($GccTarget=~/symbian/)
20963 {
20964 $OStarget = "symbian";
20965 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
20966 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020967
20968 # check GCC version
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020969 if($GCC_Ver=~/\A4\.8(|\.[012])\Z/)
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020970 { # bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57850
Andrey Ponomarenko2b029aa2013-09-27 15:31:42 +040020971 # introduced in 4.8
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040020972 # fixed in 4.8.3
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040020973 printMsg("WARNING", "Not working properly with GCC $GCC_Ver. Please update or downgrade GCC or use a local installation by --gcc-path=PATH option.");
20974 $EMERGENCY_MODE_48 = 1;
20975 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020976 }
20977 else {
20978 exitStatus("Error", "something is going wrong with the GCC compiler");
20979 }
20980 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020981 if($HSearch)
20982 {
20983 if(not $NoStdInc)
20984 { # do NOT search in GCC standard paths
20985 my %DPaths = detect_inc_default_paths();
20986 @DefaultCppPaths = @{$DPaths{"Cpp"}};
20987 @DefaultGccPaths = @{$DPaths{"Gcc"}};
20988 @DefaultIncPaths = @{$DPaths{"Inc"}};
20989 push_U($SystemPaths{"include"}, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020990 }
20991 }
20992 }
20993 if($HSearch)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020994 { # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020995 my $IncPath = "/usr/include";
20996 if($SystemRoot) {
20997 $IncPath = $SystemRoot.$IncPath;
20998 }
20999 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021000 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021001 }
21002 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021003
21004 if($ExtraInfo)
21005 {
21006 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
21007 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
21008 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021009}
21010
21011sub getLIB_EXT($)
21012{
21013 my $Target = $_[0];
21014 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
21015 return $Ext;
21016 }
21017 return $OS_LibExt{$LIB_TYPE}{"default"};
21018}
21019
21020sub getAR_EXT($)
21021{
21022 my $Target = $_[0];
21023 if(my $Ext = $OS_Archive{$Target}) {
21024 return $Ext;
21025 }
21026 return $OS_Archive{"default"};
21027}
21028
21029sub get_dumpversion($)
21030{
21031 my $Cmd = $_[0];
21032 return "" if(not $Cmd);
21033 if($Cache{"get_dumpversion"}{$Cmd}) {
21034 return $Cache{"get_dumpversion"}{$Cmd};
21035 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021036 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021037 chomp($V);
21038 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
21039}
21040
21041sub get_dumpmachine($)
21042{
21043 my $Cmd = $_[0];
21044 return "" if(not $Cmd);
21045 if($Cache{"get_dumpmachine"}{$Cmd}) {
21046 return $Cache{"get_dumpmachine"}{$Cmd};
21047 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021048 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021049 chomp($Machine);
21050 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
21051}
21052
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021053sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021054{
21055 my $Cmd = $_[0];
21056 return "" if(not $Cmd);
21057 my @Options = (
21058 "--version",
21059 "-help"
21060 );
21061 foreach my $Opt (@Options)
21062 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021063 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021064 if($Info) {
21065 return 1;
21066 }
21067 }
21068 return 0;
21069}
21070
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021071sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021072{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021073 my ($Cmd, $ReqVer) = @_;
21074 return 0 if(not $Cmd or not $ReqVer);
21075 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
21076 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021077 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021078 if(my $GccVer = get_dumpversion($Cmd))
21079 {
21080 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
21081 if(cmpVersions($GccVer, $ReqVer)>=0) {
21082 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
21083 }
21084 }
21085 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021086}
21087
21088sub get_depth($)
21089{
21090 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021091 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021092 }
21093 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
21094}
21095
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021096sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021097{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021098 return if($Cache{"registerGccHeaders"}); # this function should be called once
21099
21100 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021101 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021102 my @Headers = cmd_find($Path,"f");
21103 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21104 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021105 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021106 my $FileName = get_filename($HPath);
21107 if(not defined $DefaultGccHeader{$FileName})
21108 { # skip duplicated
21109 $DefaultGccHeader{$FileName} = $HPath;
21110 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021111 }
21112 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021113 $Cache{"registerGccHeaders"} = 1;
21114}
21115
21116sub registerCppHeaders()
21117{
21118 return if($Cache{"registerCppHeaders"}); # this function should be called once
21119
21120 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021121 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021122 my @Headers = cmd_find($CppDir,"f");
21123 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
21124 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021125 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021126 my $FileName = get_filename($Path);
21127 if(not defined $DefaultCppHeader{$FileName})
21128 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021129 $DefaultCppHeader{$FileName} = $Path;
21130 }
21131 }
21132 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021133 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021134}
21135
21136sub parse_libname($$$)
21137{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021138 return "" if(not $_[0]);
21139 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
21140 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021141 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021142 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
21143}
21144
21145sub parse_libname_I($$$)
21146{
21147 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021148
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021149 if($Target eq "symbian") {
21150 return parse_libname_symbian($Name, $Type);
21151 }
21152 elsif($Target eq "windows") {
21153 return parse_libname_windows($Name, $Type);
21154 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021155
21156 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021157 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021158 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021159 { # libSDL-1.2.so.0.7.1
21160 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021161 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021162 if($Type eq "name")
21163 { # libSDL-1.2
21164 # libwbxml2
21165 return $2;
21166 }
21167 elsif($Type eq "name+ext")
21168 { # libSDL-1.2.so
21169 # libwbxml2.so
21170 return $1;
21171 }
21172 elsif($Type eq "version")
21173 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021174 if(defined $7
21175 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021176 { # 0.7.1
21177 return $7;
21178 }
21179 else
21180 { # libc-2.5.so (=>2.5 version)
21181 my $MV = $5;
21182 $MV=~s/\A[\-\_]+//g;
21183 return $MV;
21184 }
21185 }
21186 elsif($Type eq "short")
21187 { # libSDL
21188 # libwbxml2
21189 return $3;
21190 }
21191 elsif($Type eq "shortest")
21192 { # SDL
21193 # wbxml
21194 return shortest_name($3);
21195 }
21196 }
21197 return "";# error
21198}
21199
21200sub parse_libname_symbian($$)
21201{
21202 my ($Name, $Type) = @_;
21203 my $Ext = getLIB_EXT("symbian");
21204 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
21205 { # libpthread{00010001}.dso
21206 if($Type eq "name")
21207 { # libpthread{00010001}
21208 return $2;
21209 }
21210 elsif($Type eq "name+ext")
21211 { # libpthread{00010001}.dso
21212 return $1;
21213 }
21214 elsif($Type eq "version")
21215 { # 00010001
21216 my $V = $4;
21217 $V=~s/\{(.+)\}/$1/;
21218 return $V;
21219 }
21220 elsif($Type eq "short")
21221 { # libpthread
21222 return $3;
21223 }
21224 elsif($Type eq "shortest")
21225 { # pthread
21226 return shortest_name($3);
21227 }
21228 }
21229 return "";# error
21230}
21231
21232sub parse_libname_windows($$)
21233{
21234 my ($Name, $Type) = @_;
21235 my $Ext = getLIB_EXT("windows");
21236 if($Name=~/((.+?)\.$Ext)\Z/)
21237 { # netapi32.dll
21238 if($Type eq "name")
21239 { # netapi32
21240 return $2;
21241 }
21242 elsif($Type eq "name+ext")
21243 { # netapi32.dll
21244 return $1;
21245 }
21246 elsif($Type eq "version")
21247 { # DLL version embedded
21248 # at binary-level
21249 return "";
21250 }
21251 elsif($Type eq "short")
21252 { # netapi32
21253 return $2;
21254 }
21255 elsif($Type eq "shortest")
21256 { # netapi
21257 return shortest_name($2);
21258 }
21259 }
21260 return "";# error
21261}
21262
21263sub shortest_name($)
21264{
21265 my $Name = $_[0];
21266 # remove prefix
21267 $Name=~s/\A(lib|open)//;
21268 # remove suffix
21269 $Name=~s/[\W\d_]+\Z//i;
21270 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
21271 return $Name;
21272}
21273
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021274sub createSymbolsList($$$$$)
21275{
21276 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
21277 read_ABI_Dump(1, $DPath);
21278 if(not $CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021279 prepareSymbols(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021280 }
21281 my %SymbolHeaderLib = ();
21282 my $Total = 0;
21283 # Get List
21284 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
21285 {
21286 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021287 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021288 next;
21289 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021290 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021291 { # skip other symbols
21292 next;
21293 }
21294 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
21295 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021296 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021297 next;
21298 }
21299 my $DyLib = $Symbol_Library{1}{$Symbol};
21300 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021301 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021302 next;
21303 }
21304 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
21305 $Total+=1;
21306 }
21307 # Draw List
21308 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
21309 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
21310 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
21311 {
21312 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
21313 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021314 my %NS_Symbol = ();
21315 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021316 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021317 }
21318 foreach my $NameSpace (sort keys(%NS_Symbol))
21319 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021320 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021321 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
21322 foreach my $Symbol (@SortedInterfaces)
21323 {
21324 my $SubReport = "";
21325 my $Signature = get_Signature($Symbol, 1);
21326 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021327 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021328 }
21329 if($Symbol=~/\A(_Z|\?)/)
21330 {
21331 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021332 $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 +040021333 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021334 else {
21335 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21336 }
21337 }
21338 else
21339 {
21340 if($Signature) {
21341 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21342 }
21343 else {
21344 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21345 }
21346 }
21347 $SYMBOLS_LIST .= $SubReport;
21348 }
21349 }
21350 $SYMBOLS_LIST .= "<br/>\n";
21351 }
21352 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021353 # clear info
21354 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21355 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21356 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21357 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021358 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021359 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021360 my $CssStyles = readModule("Styles", "SymbolsList.css");
21361 my $JScripts = readModule("Scripts", "Sections.js");
21362 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021363 my $Title = "$LName: public symbols";
21364 my $Keywords = "$LName, API, symbols";
21365 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021366 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021367 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021368 <br/><br/><hr/>\n".getReportFooter($LName, 1)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021369 <div style='height:999px;'></div></body></html>";
21370 writeFile($SaveTo, $SYMBOLS_LIST);
21371}
21372
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021373sub add_target_libs($)
21374{
21375 foreach (@{$_[0]}) {
21376 $TargetLibs{$_} = 1;
21377 }
21378}
21379
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021380sub is_target_lib($)
21381{
21382 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021383 if(not $LName) {
21384 return 0;
21385 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021386 if($TargetLibraryName
21387 and $LName!~/\Q$TargetLibraryName\E/) {
21388 return 0;
21389 }
21390 if(keys(%TargetLibs)
21391 and not $TargetLibs{$LName}
21392 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21393 return 0;
21394 }
21395 return 1;
21396}
21397
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021398sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021399{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021400 my ($H, $V) = @_;
21401 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021402 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021403 if($TargetHeaders{$V}{$H}) {
21404 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021405 }
21406 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021407 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021408}
21409
21410sub checkVersionNum($$)
21411{
21412 my ($LibVersion, $Path) = @_;
21413 if(my $VerNum = $TargetVersion{$LibVersion}) {
21414 return $VerNum;
21415 }
21416 my $UsedAltDescr = 0;
21417 foreach my $Part (split(/\s*,\s*/, $Path))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021418 { # try to get version string from file path
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021419 next if(isDump($Part)); # ABI dump
21420 next if($Part=~/\.(xml|desc)\Z/i); # XML descriptor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021421 my $VerNum = "";
21422 if(parse_libname($Part, "name", $OStarget))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021423 {
21424 $UsedAltDescr = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021425 $VerNum = parse_libname($Part, "version", $OStarget);
21426 if(not $VerNum) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021427 $VerNum = readStrVer($Part);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021428 }
21429 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021430 elsif(is_header($Part, 2, $LibVersion) or -d $Part)
21431 {
21432 $UsedAltDescr = 1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021433 $VerNum = readStrVer($Part);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021434 }
21435 if($VerNum ne "")
21436 {
21437 $TargetVersion{$LibVersion} = $VerNum;
21438 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021439 printMsg("WARNING", "setting version number to $VerNum (use -vnum option to change it)");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021440 }
21441 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021442 printMsg("WARNING", "setting ".($LibVersion==1?"1st":"2nd")." version number to \"$VerNum\" (use -v$LibVersion option to change it)");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021443 }
21444 return $TargetVersion{$LibVersion};
21445 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021446 }
21447 if($UsedAltDescr)
21448 {
21449 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021450 exitStatus("Error", "version number is not set (use -vnum option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021451 }
21452 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021453 exitStatus("Error", ($LibVersion==1?"1st":"2nd")." version number is not set (use -v$LibVersion option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021454 }
21455 }
21456}
21457
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021458sub readStrVer($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021459{
21460 my $Str = $_[0];
21461 return "" if(not $Str);
21462 $Str=~s/\Q$TargetLibraryName\E//g;
21463 if($Str=~/(\/|\\|\w|\A)[\-\_]*(\d+[\d\.\-]+\d+|\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021464 { # .../libssh-0.4.0/...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021465 return $2;
21466 }
21467 elsif(my $V = parse_libname($Str, "version", $OStarget)) {
21468 return $V;
21469 }
21470 return "";
21471}
21472
21473sub readLibs($)
21474{
21475 my $LibVersion = $_[0];
21476 if($OStarget eq "windows")
21477 { # dumpbin.exe will crash
21478 # without VS Environment
21479 check_win32_env();
21480 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021481 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021482 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021483 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021484}
21485
21486sub dump_sorting($)
21487{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021488 my $Hash = $_[0];
21489 return [] if(not $Hash);
21490 my @Keys = keys(%{$Hash});
21491 return [] if($#Keys<0);
21492 if($Keys[0]=~/\A\d+\Z/)
21493 { # numbers
21494 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021495 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021496 else
21497 { # strings
21498 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021499 }
21500}
21501
21502sub printMsg($$)
21503{
21504 my ($Type, $Msg) = @_;
21505 if($Type!~/\AINFO/) {
21506 $Msg = $Type.": ".$Msg;
21507 }
21508 if($Type!~/_C\Z/) {
21509 $Msg .= "\n";
21510 }
21511 if($Quiet)
21512 { # --quiet option
21513 appendFile($COMMON_LOG_PATH, $Msg);
21514 }
21515 else
21516 {
21517 if($Type eq "ERROR") {
21518 print STDERR $Msg;
21519 }
21520 else {
21521 print $Msg;
21522 }
21523 }
21524}
21525
21526sub exitStatus($$)
21527{
21528 my ($Code, $Msg) = @_;
21529 printMsg("ERROR", $Msg);
21530 exit($ERROR_CODE{$Code});
21531}
21532
21533sub exitReport()
21534{ # the tool has run without any errors
21535 printReport();
21536 if($COMPILE_ERRORS)
21537 { # errors in headers may add false positives/negatives
21538 exit($ERROR_CODE{"Compile_Error"});
21539 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021540 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21541 { # --binary
21542 exit($ERROR_CODE{"Incompatible"});
21543 }
21544 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21545 { # --source
21546 exit($ERROR_CODE{"Incompatible"});
21547 }
21548 elsif($RESULT{"Source"}{"Problems"}
21549 or $RESULT{"Binary"}{"Problems"})
21550 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021551 exit($ERROR_CODE{"Incompatible"});
21552 }
21553 else {
21554 exit($ERROR_CODE{"Compatible"});
21555 }
21556}
21557
21558sub readRules($)
21559{
21560 my $Kind = $_[0];
21561 if(not -f $RULES_PATH{$Kind}) {
21562 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21563 }
21564 my $Content = readFile($RULES_PATH{$Kind});
21565 while(my $Rule = parseTag(\$Content, "rule"))
21566 {
21567 my $RId = parseTag(\$Rule, "id");
21568 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21569 foreach my $Prop (@Properties) {
21570 if(my $Value = parseTag(\$Rule, lc($Prop)))
21571 {
21572 $Value=~s/\n[ ]*//;
21573 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21574 }
21575 }
21576 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21577 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21578 }
21579 else {
21580 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21581 }
21582 }
21583}
21584
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021585sub getReportPath($)
21586{
21587 my $Level = $_[0];
21588 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21589 if($Level eq "Binary")
21590 {
21591 if($BinaryReportPath)
21592 { # --bin-report-path
21593 return $BinaryReportPath;
21594 }
21595 elsif($OutputReportPath)
21596 { # --report-path
21597 return $OutputReportPath;
21598 }
21599 else
21600 { # default
21601 return $Dir."/abi_compat_report.$ReportFormat";
21602 }
21603 }
21604 elsif($Level eq "Source")
21605 {
21606 if($SourceReportPath)
21607 { # --src-report-path
21608 return $SourceReportPath;
21609 }
21610 elsif($OutputReportPath)
21611 { # --report-path
21612 return $OutputReportPath;
21613 }
21614 else
21615 { # default
21616 return $Dir."/src_compat_report.$ReportFormat";
21617 }
21618 }
21619 else
21620 {
21621 if($OutputReportPath)
21622 { # --report-path
21623 return $OutputReportPath;
21624 }
21625 else
21626 { # default
21627 return $Dir."/compat_report.$ReportFormat";
21628 }
21629 }
21630}
21631
21632sub printStatMsg($)
21633{
21634 my $Level = $_[0];
21635 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21636}
21637
21638sub listAffected($)
21639{
21640 my $Level = $_[0];
21641 my $List = "";
21642 foreach (keys(%{$TotalAffected{$Level}}))
21643 {
21644 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21645 { # skip "Low"-severity problems
21646 next;
21647 }
21648 $List .= "$_\n";
21649 }
21650 my $Dir = get_dirname(getReportPath($Level));
21651 if($Level eq "Binary") {
21652 writeFile($Dir."/abi_affected.txt", $List);
21653 }
21654 elsif($Level eq "Source") {
21655 writeFile($Dir."/src_affected.txt", $List);
21656 }
21657}
21658
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021659sub printReport()
21660{
21661 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021662 createReport();
21663 if($JoinReport or $DoubleReport)
21664 {
21665 if($RESULT{"Binary"}{"Problems"}
21666 or $RESULT{"Source"}{"Problems"}) {
21667 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021668 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021669 else {
21670 printMsg("INFO", "result: COMPATIBLE");
21671 }
21672 printStatMsg("Binary");
21673 printStatMsg("Source");
21674 if($ListAffected)
21675 { # --list-affected
21676 listAffected("Binary");
21677 listAffected("Source");
21678 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021679 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021680 elsif($BinaryOnly)
21681 {
21682 if($RESULT{"Binary"}{"Problems"}) {
21683 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21684 }
21685 else {
21686 printMsg("INFO", "result: COMPATIBLE");
21687 }
21688 printStatMsg("Binary");
21689 if($ListAffected)
21690 { # --list-affected
21691 listAffected("Binary");
21692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021693 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021694 elsif($SourceOnly)
21695 {
21696 if($RESULT{"Source"}{"Problems"}) {
21697 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21698 }
21699 else {
21700 printMsg("INFO", "result: COMPATIBLE");
21701 }
21702 printStatMsg("Source");
21703 if($ListAffected)
21704 { # --list-affected
21705 listAffected("Source");
21706 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021707 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021708 if($StdOut)
21709 {
21710 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021711 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021712 printMsg("INFO", "compatibility report has been generated to stdout");
21713 }
21714 else
21715 { # default
21716 printMsg("INFO", "compatibility reports have been generated to stdout");
21717 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021718 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021719 else
21720 {
21721 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021722 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021723 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21724 }
21725 elsif($DoubleReport)
21726 { # default
21727 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21728 }
21729 elsif($BinaryOnly)
21730 { # --binary
21731 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21732 }
21733 elsif($SourceOnly)
21734 { # --source
21735 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21736 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021737 }
21738}
21739
21740sub check_win32_env()
21741{
21742 if(not $ENV{"DevEnvDir"}
21743 or not $ENV{"LIB"}) {
21744 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21745 }
21746}
21747
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021748sub diffSets($$)
21749{
21750 my ($S1, $S2) = @_;
21751 my @SK1 = keys(%{$S1});
21752 my @SK2 = keys(%{$S2});
21753 if($#SK1!=$#SK2) {
21754 return 1;
21755 }
21756 foreach my $K1 (@SK1)
21757 {
21758 if(not defined $S2->{$K1}) {
21759 return 1;
21760 }
21761 }
21762 return 0;
21763}
21764
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021765sub create_ABI_Dump()
21766{
21767 if(not -e $DumpAPI) {
21768 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21769 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021770 my @DParts = split(/\s*,\s*/, $DumpAPI);
21771 foreach my $Part (@DParts)
21772 {
21773 if(not -e $Part) {
21774 exitStatus("Access_Error", "can't access \'$Part\'");
21775 }
21776 }
21777 checkVersionNum(1, $DumpAPI);
21778 foreach my $Part (@DParts)
21779 {
21780 if(isDump($Part)) {
21781 read_ABI_Dump(1, $Part);
21782 }
21783 else {
21784 readDescriptor(1, createDescriptor(1, $Part));
21785 }
21786 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021787
21788 if(not $Descriptor{1}{"Version"})
21789 { # set to default: X
21790 $Descriptor{1}{"Version"} = "X";
21791 }
21792
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021793 initLogging(1);
21794 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021795
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021796 my $DumpPath = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi";
21797 $DumpPath .= ".".$AR_EXT; # gzipped by default
21798 if($OutputDumpPath)
21799 { # user defined path
21800 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021801 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021802 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21803
21804 if(not $Archive and not $StdOut)
21805 { # check archive utilities
21806 if($OSgroup eq "windows")
21807 { # using zip
21808 my $ZipCmd = get_CmdPath("zip");
21809 if(not $ZipCmd) {
21810 exitStatus("Not_Found", "can't find \"zip\"");
21811 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021812 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021813 else
21814 { # using tar and gzip
21815 my $TarCmd = get_CmdPath("tar");
21816 if(not $TarCmd) {
21817 exitStatus("Not_Found", "can't find \"tar\"");
21818 }
21819 my $GzipCmd = get_CmdPath("gzip");
21820 if(not $GzipCmd) {
21821 exitStatus("Not_Found", "can't find \"gzip\"");
21822 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021823 }
21824 }
21825
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021826 if(not $Descriptor{1}{"Dump"})
21827 {
21828 if(not $CheckHeadersOnly) {
21829 readLibs(1);
21830 }
21831 if($CheckHeadersOnly) {
21832 setLanguage(1, "C++");
21833 }
21834 if(not $CheckObjectsOnly) {
21835 searchForHeaders(1);
21836 }
21837 $WORD_SIZE{1} = detectWordSize();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021838 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021839 if(not $Descriptor{1}{"Dump"})
21840 {
21841 if($Descriptor{1}{"Headers"}) {
21842 readHeaders(1);
21843 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021844 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021845 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021846 if(not keys(%{$SymbolInfo{1}}))
21847 { # check if created dump is valid
21848 if(not $ExtendedCheck and not $CheckObjectsOnly)
21849 {
21850 if($CheckHeadersOnly) {
21851 exitStatus("Empty_Set", "the set of public symbols is empty");
21852 }
21853 else {
21854 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21855 }
21856 }
21857 }
21858 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021859 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021860 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21861 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021862 if($ExtraDump)
21863 { # add unmangled names to the ABI dump
21864 my @Names = ();
21865 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21866 {
21867 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21868 push(@Names, $MnglName);
21869 }
21870 }
21871 translateSymbols(@Names, 1);
21872 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21873 {
21874 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21875 {
21876 if(my $Unmangled = $tr_name{$MnglName})
21877 {
21878 if($MnglName ne $Unmangled) {
21879 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21880 }
21881 }
21882 }
21883 }
21884 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021885
21886 my %GccConstants = (); # built-in GCC constants
21887 foreach my $Name (keys(%{$Constants{1}}))
21888 {
21889 if(not defined $Constants{1}{$Name}{"Header"})
21890 {
21891 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21892 delete($Constants{1}{$Name});
21893 }
21894 }
21895
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021896 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021897 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021898 "TypeInfo" => $TypeInfo{1},
21899 "SymbolInfo" => $SymbolInfo{1},
21900 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021901 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021902 "SymbolVersion" => $SymVer{1},
21903 "LibraryVersion" => $Descriptor{1}{"Version"},
21904 "LibraryName" => $TargetLibraryName,
21905 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021906 "SkipTypes" => $SkipTypes{1},
21907 "SkipSymbols" => $SkipSymbols{1},
21908 "SkipNameSpaces" => $SkipNameSpaces{1},
21909 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021910 "Headers" => \%HeadersInfo,
21911 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021912 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021913 "NameSpaces" => $NestedNameSpaces{1},
21914 "Target" => $OStarget,
21915 "Arch" => getArch(1),
21916 "WordSize" => $WORD_SIZE{1},
21917 "GccVersion" => get_dumpversion($GCC_PATH),
21918 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21919 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21920 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021921 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021922 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021923 }
21924 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021925 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021926 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021927 if($ExtendedCheck)
21928 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021929 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021930 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021931 if($BinaryOnly)
21932 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021933 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021934 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021935 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021936 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021937 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021938 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21939 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021940 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021941
21942 my $ABI_DUMP = "";
21943 if($UseXML)
21944 {
21945 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021946 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021947 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021948 else
21949 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021950 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021951 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021952 if($StdOut)
21953 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021954 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021955 printMsg("INFO", "ABI dump has been generated to stdout");
21956 return;
21957 }
21958 else
21959 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021960 my ($DDir, $DName) = separate_path($DumpPath);
21961 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021962 if(not $Archive) {
21963 $DPath = $DumpPath;
21964 }
21965
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021966 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021967
21968 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021969 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021970 close(DUMP);
21971
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021972 if(not -s $DPath) {
21973 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21974 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021975 if($Archive) {
21976 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021977 }
21978
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021979 if($OutputDumpPath) {
21980 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021981 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021982 else {
21983 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
21984 }
21985 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 +040021986 }
21987}
21988
21989sub quickEmptyReports()
21990{ # Quick "empty" reports
21991 # 4 times faster than merging equal dumps
21992 # NOTE: the dump contains the "LibraryVersion" attribute
21993 # if you change the version, then your dump will be different
21994 # OVERCOME: use -v1 and v2 options for comparing dumps
21995 # and don't change version in the XML descriptor (and dumps)
21996 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
21997 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
21998 {
21999 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
22000 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
22001 if($FilePath1 and $FilePath2)
22002 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022003 my $Line = readLineNum($FilePath1, 0);
22004 if($Line=~/xml/)
22005 { # XML format
22006 # is not supported yet
22007 return;
22008 }
22009
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022010 local $/ = undef;
22011
22012 open(DUMP1, $FilePath1);
22013 my $Content1 = <DUMP1>;
22014 close(DUMP1);
22015
22016 open(DUMP2, $FilePath2);
22017 my $Content2 = <DUMP2>;
22018 close(DUMP2);
22019
22020 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022021 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022022 # clean memory
22023 undef $Content2;
22024
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022025 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022026 my $ABIdump = eval($Content1);
22027
22028 # clean memory
22029 undef $Content1;
22030
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022031 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022032 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 +040022033 }
22034 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022035 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022036 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
22037 }
22038 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022039 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022040 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
22041 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022042 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022043 read_Libs_DumpInfo($ABIdump, 1);
22044 read_Machine_DumpInfo($ABIdump, 1);
22045 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022046
22047 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
22048 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
22049
22050 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
22051 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
22052
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022053 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
22054 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
22055 exitReport();
22056 }
22057 }
22058 }
22059}
22060
22061sub initLogging($)
22062{
22063 my $LibVersion = $_[0];
22064 # create log directory
22065 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
22066 if($OutputLogPath{$LibVersion})
22067 { # user-defined by -log-path option
22068 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
22069 }
22070 if($LogMode ne "n") {
22071 mkpath($LOG_DIR);
22072 }
22073 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022074 if($Debug)
22075 { # debug directory
22076 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022077
22078 if(not $ExtraInfo)
22079 { # enable --extra-info
22080 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
22081 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022082 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022083 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022084}
22085
22086sub writeLog($$)
22087{
22088 my ($LibVersion, $Msg) = @_;
22089 if($LogMode ne "n") {
22090 appendFile($LOG_PATH{$LibVersion}, $Msg);
22091 }
22092}
22093
22094sub resetLogging($)
22095{
22096 my $LibVersion = $_[0];
22097 if($LogMode!~/a|n/)
22098 { # remove old log
22099 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022100 if($Debug) {
22101 rmtree($DEBUG_PATH{$LibVersion});
22102 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022103 }
22104}
22105
22106sub printErrorLog($)
22107{
22108 my $LibVersion = $_[0];
22109 if($LogMode ne "n") {
22110 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
22111 }
22112}
22113
22114sub isDump($)
22115{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022116 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz|\.zip|\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022117 return $1;
22118 }
22119 return 0;
22120}
22121
22122sub isDump_U($)
22123{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022124 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022125 return $1;
22126 }
22127 return 0;
22128}
22129
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022130sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022131{
22132 # read input XML descriptors or ABI dumps
22133 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022134 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022135 }
22136 my @DParts1 = split(/\s*,\s*/, $Descriptor{1}{"Path"});
22137 foreach my $Part (@DParts1)
22138 {
22139 if(not -e $Part) {
22140 exitStatus("Access_Error", "can't access \'$Part\'");
22141 }
22142 }
22143 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040022144 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022145 }
22146 my @DParts2 = split(/\s*,\s*/, $Descriptor{2}{"Path"});
22147 foreach my $Part (@DParts2)
22148 {
22149 if(not -e $Part) {
22150 exitStatus("Access_Error", "can't access \'$Part\'");
22151 }
22152 }
22153 detect_default_paths("bin"); # to extract dumps
22154 if($#DParts1==0 and $#DParts2==0
22155 and isDump($Descriptor{1}{"Path"})
22156 and isDump($Descriptor{2}{"Path"}))
22157 { # optimization: equal ABI dumps
22158 quickEmptyReports();
22159 }
22160 checkVersionNum(1, $Descriptor{1}{"Path"});
22161 checkVersionNum(2, $Descriptor{2}{"Path"});
22162 printMsg("INFO", "preparation, please wait ...");
22163 foreach my $Part (@DParts1)
22164 {
22165 if(isDump($Part)) {
22166 read_ABI_Dump(1, $Part);
22167 }
22168 else {
22169 readDescriptor(1, createDescriptor(1, $Part));
22170 }
22171 }
22172 foreach my $Part (@DParts2)
22173 {
22174 if(isDump($Part)) {
22175 read_ABI_Dump(2, $Part);
22176 }
22177 else {
22178 readDescriptor(2, createDescriptor(2, $Part));
22179 }
22180 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022181
22182 if(not $Descriptor{1}{"Version"})
22183 { # set to default: X
22184 $Descriptor{1}{"Version"} = "X";
22185 }
22186
22187 if(not $Descriptor{2}{"Version"})
22188 { # set to default: Y
22189 $Descriptor{2}{"Version"} = "Y";
22190 }
22191
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022192 initLogging(1);
22193 initLogging(2);
22194 # check consistency
22195 if(not $Descriptor{1}{"Headers"}
22196 and not $Descriptor{1}{"Libs"}) {
22197 exitStatus("Error", "descriptor d1 does not contain both header files and libraries info");
22198 }
22199 if(not $Descriptor{2}{"Headers"}
22200 and not $Descriptor{2}{"Libs"}) {
22201 exitStatus("Error", "descriptor d2 does not contain both header files and libraries info");
22202 }
22203 if($Descriptor{1}{"Headers"} and not $Descriptor{1}{"Libs"}
22204 and not $Descriptor{2}{"Headers"} and $Descriptor{2}{"Libs"}) {
22205 exitStatus("Error", "can't compare headers with $SLIB_TYPE libraries");
22206 }
22207 elsif(not $Descriptor{1}{"Headers"} and $Descriptor{1}{"Libs"}
22208 and $Descriptor{2}{"Headers"} and not $Descriptor{2}{"Libs"}) {
22209 exitStatus("Error", "can't compare $SLIB_TYPE libraries with headers");
22210 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022211 if(not $Descriptor{1}{"Headers"})
22212 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022213 if($CheckHeadersOnly_Opt) {
22214 exitStatus("Error", "can't find header files info in descriptor d1");
22215 }
22216 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022217 if(not $Descriptor{2}{"Headers"})
22218 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022219 if($CheckHeadersOnly_Opt) {
22220 exitStatus("Error", "can't find header files info in descriptor d2");
22221 }
22222 }
22223 if(not $Descriptor{1}{"Headers"}
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022224 or not $Descriptor{2}{"Headers"})
22225 {
22226 if(not $CheckObjectsOnly_Opt)
22227 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022228 printMsg("WARNING", "comparing $SLIB_TYPE libraries only");
22229 $CheckObjectsOnly = 1;
22230 }
22231 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022232 if(not $Descriptor{1}{"Libs"})
22233 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022234 if($CheckObjectsOnly_Opt) {
22235 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d1");
22236 }
22237 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040022238 if(not $Descriptor{2}{"Libs"})
22239 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022240 if($CheckObjectsOnly_Opt) {
22241 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d2");
22242 }
22243 }
22244 if(not $Descriptor{1}{"Libs"}
22245 or not $Descriptor{2}{"Libs"})
22246 { # comparing standalone header files
22247 # comparing ABI dumps created with --headers-only
22248 if(not $CheckHeadersOnly_Opt)
22249 {
22250 printMsg("WARNING", "checking headers only");
22251 $CheckHeadersOnly = 1;
22252 }
22253 }
22254 if($UseDumps)
22255 { # --use-dumps
22256 # parallel processing
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022257 my $DumpPath1 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi.$AR_EXT";
22258 my $DumpPath2 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{2}{"Version"}.".abi.$AR_EXT";
22259
22260 unlink($DumpPath1);
22261 unlink($DumpPath2);
22262
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022263 my $pid = fork();
22264 if($pid)
22265 { # dump on two CPU cores
22266 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
22267 if($RelativeDirectory{1}) {
22268 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
22269 }
22270 if($OutputLogPath{1}) {
22271 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
22272 }
22273 if($CrossGcc) {
22274 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22275 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022276 if($Quiet)
22277 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022278 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022279 @PARAMS = (@PARAMS, "-logging-mode", "a");
22280 }
22281 elsif($LogMode and $LogMode ne "w")
22282 { # "w" is default
22283 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022284 }
22285 if($ExtendedCheck) {
22286 @PARAMS = (@PARAMS, "-extended");
22287 }
22288 if($UserLang) {
22289 @PARAMS = (@PARAMS, "-lang", $UserLang);
22290 }
22291 if($TargetVersion{1}) {
22292 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
22293 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022294 if($BinaryOnly) {
22295 @PARAMS = (@PARAMS, "-binary");
22296 }
22297 if($SourceOnly) {
22298 @PARAMS = (@PARAMS, "-source");
22299 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022300 if($SortDump) {
22301 @PARAMS = (@PARAMS, "-sort");
22302 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022303 if($DumpFormat and $DumpFormat ne "perl") {
22304 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22305 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022306 if($CheckHeadersOnly) {
22307 @PARAMS = (@PARAMS, "-headers-only");
22308 }
22309 if($CheckObjectsOnly) {
22310 @PARAMS = (@PARAMS, "-objects-only");
22311 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022312 if($Debug)
22313 {
22314 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022315 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022317 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022318 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022319 exit(1);
22320 }
22321 }
22322 else
22323 { # child
22324 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22325 if($RelativeDirectory{2}) {
22326 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22327 }
22328 if($OutputLogPath{2}) {
22329 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22330 }
22331 if($CrossGcc) {
22332 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22333 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022334 if($Quiet)
22335 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022336 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022337 @PARAMS = (@PARAMS, "-logging-mode", "a");
22338 }
22339 elsif($LogMode and $LogMode ne "w")
22340 { # "w" is default
22341 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022342 }
22343 if($ExtendedCheck) {
22344 @PARAMS = (@PARAMS, "-extended");
22345 }
22346 if($UserLang) {
22347 @PARAMS = (@PARAMS, "-lang", $UserLang);
22348 }
22349 if($TargetVersion{2}) {
22350 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22351 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022352 if($BinaryOnly) {
22353 @PARAMS = (@PARAMS, "-binary");
22354 }
22355 if($SourceOnly) {
22356 @PARAMS = (@PARAMS, "-source");
22357 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022358 if($SortDump) {
22359 @PARAMS = (@PARAMS, "-sort");
22360 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022361 if($DumpFormat and $DumpFormat ne "perl") {
22362 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22363 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022364 if($CheckHeadersOnly) {
22365 @PARAMS = (@PARAMS, "-headers-only");
22366 }
22367 if($CheckObjectsOnly) {
22368 @PARAMS = (@PARAMS, "-objects-only");
22369 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022370 if($Debug)
22371 {
22372 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022373 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022374 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022375 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022376 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022377 exit(1);
22378 }
22379 else {
22380 exit(0);
22381 }
22382 }
22383 waitpid($pid, 0);
22384 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022385 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22386 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022387 if($TargetLibraryFName ne $TargetLibraryName) {
22388 @CMP_PARAMS = (@CMP_PARAMS, "-l-full", $TargetLibraryFName);
22389 }
22390 if($ShowRetVal) {
22391 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22392 }
22393 if($CrossGcc) {
22394 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22395 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022396 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22397 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022398 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022399 }
22400 if($ReportFormat and $ReportFormat ne "html")
22401 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022402 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22403 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022404 if($OutputReportPath) {
22405 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22406 }
22407 if($BinaryReportPath) {
22408 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22409 }
22410 if($SourceReportPath) {
22411 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22412 }
22413 if($LoggingPath) {
22414 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22415 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022416 if($CheckHeadersOnly) {
22417 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22418 }
22419 if($CheckObjectsOnly) {
22420 @CMP_PARAMS = (@CMP_PARAMS, "-objects-only");
22421 }
22422 if($BinaryOnly) {
22423 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22424 }
22425 if($SourceOnly) {
22426 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22427 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022428 if($Browse) {
22429 @CMP_PARAMS = (@CMP_PARAMS, "-browse", $Browse);
22430 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022431 if($OpenReport) {
22432 @CMP_PARAMS = (@CMP_PARAMS, "-open");
22433 }
22434 if($Debug)
22435 {
22436 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22437 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022438 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022439 system("perl", $0, @CMP_PARAMS);
22440 exit($?>>8);
22441 }
22442 if(not $Descriptor{1}{"Dump"}
22443 or not $Descriptor{2}{"Dump"})
22444 { # need GCC toolchain to analyze
22445 # header files and libraries
22446 detect_default_paths("inc|lib|gcc");
22447 }
22448 if(not $Descriptor{1}{"Dump"})
22449 {
22450 if(not $CheckHeadersOnly) {
22451 readLibs(1);
22452 }
22453 if($CheckHeadersOnly) {
22454 setLanguage(1, "C++");
22455 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022456 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022457 searchForHeaders(1);
22458 }
22459 $WORD_SIZE{1} = detectWordSize();
22460 }
22461 if(not $Descriptor{2}{"Dump"})
22462 {
22463 if(not $CheckHeadersOnly) {
22464 readLibs(2);
22465 }
22466 if($CheckHeadersOnly) {
22467 setLanguage(2, "C++");
22468 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022469 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022470 searchForHeaders(2);
22471 }
22472 $WORD_SIZE{2} = detectWordSize();
22473 }
22474 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22475 { # support for old ABI dumps
22476 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022477 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022478 {
22479 $WORD_SIZE{1} = $WORD_SIZE{2};
22480 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22481 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022482 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022483 {
22484 $WORD_SIZE{2} = $WORD_SIZE{1};
22485 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22486 }
22487 }
22488 elsif(not $WORD_SIZE{1}
22489 and not $WORD_SIZE{2})
22490 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022491 $WORD_SIZE{1} = "4";
22492 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022493 }
22494 if($Descriptor{1}{"Dump"})
22495 { # support for old ABI dumps
22496 prepareTypes(1);
22497 }
22498 if($Descriptor{2}{"Dump"})
22499 { # support for old ABI dumps
22500 prepareTypes(2);
22501 }
22502 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22503 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22504 }
22505 # started to process input data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022506 if(not $CheckObjectsOnly)
22507 {
22508 if($Descriptor{1}{"Headers"}
22509 and not $Descriptor{1}{"Dump"}) {
22510 readHeaders(1);
22511 }
22512 if($Descriptor{2}{"Headers"}
22513 and not $Descriptor{2}{"Dump"}) {
22514 readHeaders(2);
22515 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022516 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022517
22518 # clean memory
22519 %SystemHeaders = ();
22520 %mangled_name_gcc = ();
22521
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022522 prepareSymbols(1);
22523 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022524
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022525 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022526 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022527
22528 # Virtual Tables
22529 registerVTable(1);
22530 registerVTable(2);
22531
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022532 if(not checkDump(1, "1.22")
22533 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022534 { # support for old ABI dumps
22535 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22536 {
22537 if($ClassName=~/</)
22538 { # templates
22539 if(not defined $VirtualTable{1}{$ClassName})
22540 { # synchronize
22541 delete($VirtualTable{2}{$ClassName});
22542 }
22543 }
22544 }
22545 }
22546
22547 registerOverriding(1);
22548 registerOverriding(2);
22549
22550 setVirtFuncPositions(1);
22551 setVirtFuncPositions(2);
22552
22553 # Other
22554 addParamNames(1);
22555 addParamNames(2);
22556
22557 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022558}
22559
22560sub compareAPIs($)
22561{
22562 my $Level = $_[0];
22563 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022564 loadModule("CallConv");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022565 if($Level eq "Binary") {
22566 printMsg("INFO", "comparing ABIs ...");
22567 }
22568 else {
22569 printMsg("INFO", "comparing APIs ...");
22570 }
22571 if($CheckHeadersOnly
22572 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022573 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022574 detectAdded_H($Level);
22575 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022576 }
22577 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022578 { # added/removed in libs
22579 detectAdded($Level);
22580 detectRemoved($Level);
22581 }
22582 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022583 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022584 mergeSymbols($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022585 if(keys(%{$CheckedSymbols{$Level}})) {
22586 mergeConstants($Level);
22587 }
22588 }
Andrey Ponomarenkof442c172013-07-30 19:08:11 +040022589
22590 $Cache{"mergeTypes"} = (); # free memory
22591
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022592 if($CheckHeadersOnly
22593 or $Level eq "Source")
22594 { # added/removed in headers
22595 mergeHeaders($Level);
22596 }
22597 else
22598 { # added/removed in libs
22599 mergeLibs($Level);
22600 if($CheckImpl
22601 and $Level eq "Binary") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022602 mergeImpl();
22603 }
22604 }
22605}
22606
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022607sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022608{
22609 my %Opts = (
22610 "OStarget"=>$OStarget,
22611 "Debug"=>$Debug,
22612 "Quiet"=>$Quiet,
22613 "LogMode"=>$LogMode,
22614 "CheckHeadersOnly"=>$CheckHeadersOnly,
22615
22616 "SystemRoot"=>$SystemRoot,
22617 "MODULES_DIR"=>$MODULES_DIR,
22618 "GCC_PATH"=>$GCC_PATH,
22619 "TargetSysInfo"=>$TargetSysInfo,
22620 "CrossPrefix"=>$CrossPrefix,
22621 "TargetLibraryName"=>$TargetLibraryName,
22622 "CrossGcc"=>$CrossGcc,
22623 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022624 "NoStdInc"=>$NoStdInc,
22625
22626 "BinaryOnly" => $BinaryOnly,
22627 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022628 );
22629 return \%Opts;
22630}
22631
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022632sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022633{
22634 my %CODE_ERROR = reverse(%ERROR_CODE);
22635 return $CODE_ERROR{$_[0]};
22636}
22637
22638sub scenario()
22639{
22640 if($StdOut)
22641 { # enable quiet mode
22642 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022643 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022644 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022645 if(not $LogMode)
22646 { # default
22647 $LogMode = "w";
22648 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022649 if($UserLang)
22650 { # --lang=C++
22651 $UserLang = uc($UserLang);
22652 $COMMON_LANGUAGE{1}=$UserLang;
22653 $COMMON_LANGUAGE{2}=$UserLang;
22654 }
22655 if($LoggingPath)
22656 {
22657 $OutputLogPath{1} = $LoggingPath;
22658 $OutputLogPath{2} = $LoggingPath;
22659 if($Quiet) {
22660 $COMMON_LOG_PATH = $LoggingPath;
22661 }
22662 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022663 if($Quick) {
22664 $ADD_TMPL_INSTANCES = 0;
22665 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022666 if($OutputDumpPath)
22667 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022668 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022669 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22670 }
22671 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022672 if($BinaryOnly and $SourceOnly)
22673 { # both --binary and --source
22674 # is the default mode
22675 $DoubleReport = 1;
22676 $JoinReport = 0;
22677 $BinaryOnly = 0;
22678 $SourceOnly = 0;
22679 if($OutputReportPath)
22680 { # --report-path
22681 $DoubleReport = 0;
22682 $JoinReport = 1;
22683 }
22684 }
22685 elsif($BinaryOnly or $SourceOnly)
22686 { # --binary or --source
22687 $DoubleReport = 0;
22688 $JoinReport = 0;
22689 }
22690 if($UseXML)
22691 { # --xml option
22692 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022693 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022694 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022695 if($ReportFormat)
22696 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022697 $ReportFormat = lc($ReportFormat);
22698 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022699 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022700 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022701 if($ReportFormat eq "htm")
22702 { # HTM == HTML
22703 $ReportFormat = "html";
22704 }
22705 elsif($ReportFormat eq "xml")
22706 { # --report-format=XML equal to --xml
22707 $UseXML = 1;
22708 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022709 }
22710 else
22711 { # default: HTML
22712 $ReportFormat = "html";
22713 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022714 if($DumpFormat)
22715 { # validate
22716 $DumpFormat = lc($DumpFormat);
22717 if($DumpFormat!~/\A(xml|perl)\Z/) {
22718 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22719 }
22720 if($DumpFormat eq "xml")
22721 { # --dump-format=XML equal to --xml
22722 $UseXML = 1;
22723 }
22724 }
22725 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022726 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022727 $DumpFormat = "perl";
22728 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022729 if($Quiet and $LogMode!~/a|n/)
22730 { # --quiet log
22731 if(-f $COMMON_LOG_PATH) {
22732 unlink($COMMON_LOG_PATH);
22733 }
22734 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022735 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022736 $CheckUndefined = 1;
22737 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022738 if($TestTool and $UseDumps)
22739 { # --test && --use-dumps == --test-dump
22740 $TestDump = 1;
22741 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022742 if($Tolerant)
22743 { # enable all
22744 $Tolerance = 1234;
22745 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022746 if($Help)
22747 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022748 HELP_MESSAGE();
22749 exit(0);
22750 }
22751 if($InfoMsg) {
22752 INFO_MESSAGE();
22753 exit(0);
22754 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022755 if($ShowVersion)
22756 {
Andrey Ponomarenkod5958082014-01-23 13:36:03 +040022757 printMsg("INFO", "ABI Compliance Checker (ACC) $TOOL_VERSION\nCopyright (C) 2014 ROSA 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 +040022758 exit(0);
22759 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022760 if($DumpVersion)
22761 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022762 printMsg("INFO", $TOOL_VERSION);
22763 exit(0);
22764 }
22765 if($ExtendedCheck) {
22766 $CheckHeadersOnly = 1;
22767 }
22768 if($SystemRoot_Opt)
22769 { # user defined root
22770 if(not -e $SystemRoot_Opt) {
22771 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22772 }
22773 $SystemRoot = $SystemRoot_Opt;
22774 $SystemRoot=~s/[\/]+\Z//g;
22775 if($SystemRoot) {
22776 $SystemRoot = get_abs_path($SystemRoot);
22777 }
22778 }
22779 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022780
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022781 if($SortDump)
22782 {
22783 $Data::Dumper::Useperl = 1;
22784 $Data::Dumper::Sortkeys = \&dump_sorting;
22785 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022786
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022787 if($TargetLibsPath)
22788 {
22789 if(not -f $TargetLibsPath) {
22790 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22791 }
22792 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22793 $TargetLibs{$Lib} = 1;
22794 }
22795 }
22796 if($TargetHeadersPath)
22797 { # --headers-list
22798 if(not -f $TargetHeadersPath) {
22799 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22800 }
22801 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22802 {
22803 $TargetHeaders{1}{$Header} = 1;
22804 $TargetHeaders{2}{$Header} = 1;
22805 }
22806 }
22807 if($TargetHeader)
22808 { # --header
22809 $TargetHeaders{1}{$TargetHeader} = 1;
22810 $TargetHeaders{2}{$TargetHeader} = 1;
22811 }
22812 if($TestTool
22813 or $TestDump)
22814 { # --test, --test-dump
22815 detect_default_paths("bin|gcc"); # to compile libs
22816 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022817 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
22818 $LIB_EXT, $GCC_PATH, $Browse, $OpenReport, $SortDump, $CheckHeadersOnly, $CheckObjectsOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022819 exit(0);
22820 }
22821 if($DumpSystem)
22822 { # --dump-system
22823 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022824 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022825 { # system XML descriptor
22826 if(not -f $DumpSystem) {
22827 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22828 }
22829 my $Ret = readSystemDescriptor(readFile($DumpSystem));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022830 foreach (@{$Ret->{"Tools"}})
22831 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022832 push_U($SystemPaths{"bin"}, $_);
22833 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022834 }
22835 if($Ret->{"CrossPrefix"}) {
22836 $CrossPrefix = $Ret->{"CrossPrefix"};
22837 }
22838 }
22839 elsif($SystemRoot_Opt)
22840 { # -sysroot "/" option
22841 # default target: /usr/lib, /usr/include
22842 # search libs: /usr/lib and /lib
22843 if(not -e $SystemRoot."/usr/lib") {
22844 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22845 }
22846 if(not -e $SystemRoot."/lib") {
22847 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22848 }
22849 if(not -e $SystemRoot."/usr/include") {
22850 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22851 }
22852 readSystemDescriptor("
22853 <name>
22854 $DumpSystem
22855 </name>
22856 <headers>
22857 $SystemRoot/usr/include
22858 </headers>
22859 <libs>
22860 $SystemRoot/usr/lib
22861 </libs>
22862 <search_libs>
22863 $SystemRoot/lib
22864 </search_libs>");
22865 }
22866 else {
22867 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22868 }
22869 detect_default_paths("bin|gcc"); # to check symbols
22870 if($OStarget eq "windows")
22871 { # to run dumpbin.exe
22872 # and undname.exe
22873 check_win32_env();
22874 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022875 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022876 exit(0);
22877 }
22878 if($CmpSystems)
22879 { # --cmp-systems
22880 detect_default_paths("bin"); # to extract dumps
22881 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022882 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022883 exit(0);
22884 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022885 if($GenerateTemplate)
22886 {
22887 writeFile("VERSION.xml", $DescriptorTemplate."\n");
22888 printMsg("INFO", "XML-descriptor template ./VERSION.xml has been generated");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022889 exit(0);
22890 }
22891 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022892 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022893 }
22894 else
22895 { # validate library name
22896 if($TargetLibraryName=~/[\*\/\\]/) {
22897 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22898 }
22899 }
22900 if(not $TargetLibraryFName) {
22901 $TargetLibraryFName = $TargetLibraryName;
22902 }
22903 if($CheckHeadersOnly_Opt and $CheckObjectsOnly_Opt) {
22904 exitStatus("Error", "you can't specify both -headers-only and -objects-only options at the same time");
22905 }
22906 if($SymbolsListPath)
22907 {
22908 if(not -f $SymbolsListPath) {
22909 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22910 }
22911 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22912 $SymbolsList{$Interface} = 1;
22913 }
22914 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022915 if($SkipSymbolsListPath)
22916 {
22917 if(not -f $SkipSymbolsListPath) {
22918 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22919 }
22920 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath))) {
22921 $SkipSymbolsList{$Interface} = 1;
22922 }
22923 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022924 if($SkipHeadersPath)
22925 {
22926 if(not -f $SkipHeadersPath) {
22927 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22928 }
22929 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022930 { # register for both versions
22931 $SkipHeadersList{1}{$Path} = 1;
22932 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022933 my ($CPath, $Type) = classifyPath($Path);
22934 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022935 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022936 }
22937 }
22938 if($ParamNamesPath)
22939 {
22940 if(not -f $ParamNamesPath) {
22941 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22942 }
22943 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22944 {
22945 if($Line=~s/\A(\w+)\;//)
22946 {
22947 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022948 if($Line=~/;(\d+);/)
22949 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022950 while($Line=~s/(\d+);(\w+)//) {
22951 $AddIntParams{$Interface}{$1}=$2;
22952 }
22953 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022954 else
22955 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022956 my $Num = 0;
22957 foreach my $Name (split(/;/, $Line)) {
22958 $AddIntParams{$Interface}{$Num++}=$Name;
22959 }
22960 }
22961 }
22962 }
22963 }
22964 if($AppPath)
22965 {
22966 if(not -f $AppPath) {
22967 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22968 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022969 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022970 $SymbolsList_App{$Interface} = 1;
22971 }
22972 }
22973 if($DumpAPI)
22974 { # --dump-abi
22975 # make an API dump
22976 create_ABI_Dump();
22977 exit($COMPILE_ERRORS);
22978 }
22979 # default: compare APIs
22980 # -d1 <path>
22981 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022982 compareInit();
22983 if($JoinReport or $DoubleReport)
22984 {
22985 compareAPIs("Binary");
22986 compareAPIs("Source");
22987 }
22988 elsif($BinaryOnly) {
22989 compareAPIs("Binary");
22990 }
22991 elsif($SourceOnly) {
22992 compareAPIs("Source");
22993 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022994 exitReport();
22995}
22996
22997scenario();