blob: 9603b1039999d52417616e4692b11d4b8fe222f1 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +04003# ABI Compliance Checker (ACC) 1.99.3
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 Ponomarenko8f4b9812013-02-07 19:11:42 +04009# Copyright (C) 2011-2013 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 Ponomarenko989a50b2012-04-03 12:24:22 +040020# - G++ (3.0-4.7, 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# =============
41# ABI Dumper >= 0.97
42#
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 Ponomarenko3e69aa32013-06-26 15:38:07 +040067my $TOOL_VERSION = "1.99.3";
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 Ponomarenkofe00e7e2013-05-24 16:48:30 +040070my $XML_REPORT_VERSION = "1.1";
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,
96$CheckInfo);
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 Ponomarenkoab282102012-03-11 11:57:02 +0400157Copyright (C) 2012 ROSA Laboratory
158License: 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 Ponomarenkoab282102012-03-11 11:57:02 +0400249# other options
250 "test!" => \$TestTool,
251 "test-dump!" => \$TestDump,
252 "debug!" => \$Debug,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400253 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400254 "p|params=s" => \$ParamNamesPath,
255 "relpath1|relpath=s" => \$RelativeDirectory{1},
256 "relpath2=s" => \$RelativeDirectory{2},
257 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400258 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400259 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400260 "bin-report-path=s" => \$BinaryReportPath,
261 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400262 "log-path=s" => \$LoggingPath,
263 "log1-path=s" => \$OutputLogPath{1},
264 "log2-path=s" => \$OutputLogPath{2},
265 "logging-mode=s" => \$LogMode,
266 "list-affected!" => \$ListAffected,
267 "l-full|lib-full=s" => \$TargetLibraryFName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400268 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400269 "b|browse=s" => \$Browse,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400270 "open!" => \$OpenReport,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400271 "extra-info=s" => \$ExtraInfo,
272 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400273 "force!" => \$Force,
274 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400275 "tolerant!" => \$Tolerant,
276 "check!" => \$CheckInfo
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400277) or ERR_MESSAGE();
278
279sub ERR_MESSAGE()
280{
281 printMsg("INFO", "\n".$ShortUsage);
282 exit($ERROR_CODE{"Error"});
283}
284
285my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
286my $SLIB_TYPE = $LIB_TYPE;
287if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
288{ # show as "shared" library
289 $SLIB_TYPE = "shared";
290}
291my $LIB_EXT = getLIB_EXT($OSgroup);
292my $AR_EXT = getAR_EXT($OSgroup);
293my $BYTE_SIZE = 8;
294my $COMMON_LOG_PATH = "logs/run.log";
295
296my $HelpMessage="
297NAME:
298 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400299 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400300
301DESCRIPTION:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400302 ABI Compliance Checker (ACC) is a tool for checking backward binary and
303 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
304 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
305 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
306 and/or source-level compatibility: changes in calling stack, v-table changes,
307 removed symbols, renamed fields, etc. Binary incompatibility may result in
308 crashing or incorrect behavior of applications built with an old version of
309 a library if they run on a new one. Source incompatibility may result in
310 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400311
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400312 The tool is intended for developers of software libraries and maintainers
313 of operating systems who are interested in ensuring backward compatibility,
314 i.e. allow old applications to run or to be recompiled with newer library
315 versions.
316
317 Also the tool can be used by ISVs for checking applications portability to
318 new library versions. Found issues can be taken into account when adapting
319 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400320
321 This tool is free software: you can redistribute it and/or modify it
322 under the terms of the GNU LGPL or GNU GPL.
323
324USAGE:
325 $CmdName [options]
326
327EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400328 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400329
330 OLD.xml and NEW.xml are XML-descriptors:
331
332 <version>
333 1.0
334 </version>
335
336 <headers>
337 /path1/to/header(s)/
338 /path2/to/header(s)/
339 ...
340 </headers>
341
342 <libs>
343 /path1/to/library(ies)/
344 /path2/to/library(ies)/
345 ...
346 </libs>
347
348INFORMATION OPTIONS:
349 -h|-help
350 Print this help.
351
352 -i|-info
353 Print complete info.
354
355 -v|-version
356 Print version information.
357
358 -dumpversion
359 Print the tool version ($TOOL_VERSION) and don't do anything else.
360
361GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400362 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400363 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400364
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400365 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400366 Descriptor of 1st (old) library version.
367 It may be one of the following:
368
369 1. XML-descriptor (VERSION.xml file):
370
371 <version>
372 1.0
373 </version>
374
375 <headers>
376 /path1/to/header(s)/
377 /path2/to/header(s)/
378 ...
379 </headers>
380
381 <libs>
382 /path1/to/library(ies)/
383 /path2/to/library(ies)/
384 ...
385 </libs>
386
387 ... (XML-descriptor template
388 can be generated by -d option)
389
390 2. ABI dump generated by -dump option
391 3. Directory with headers and/or $SLIB_TYPE libraries
392 4. Single header file
393 5. Single $SLIB_TYPE library
394 6. Comma separated list of headers and/or libraries
395
396 If you are using an 2-6 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400397 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400398
399 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400400 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400401
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400402 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400403 Descriptor of 2nd (new) library version.
404
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400405 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400406 Create library ABI dump for the input XML descriptor. You can
407 transfer it anywhere and pass instead of the descriptor. Also
408 it can be used for debugging the tool.
409
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400410 Supported ABI dump versions: 2.0<=V<=$ABI_DUMP_VERSION
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400411
412 -old-dumps
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400413 Enable support for old-version ABI dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0).\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400414
415sub HELP_MESSAGE() {
416 printMsg("INFO", $HelpMessage."
417MORE INFO:
418 $CmdName --info\n");
419}
420
421sub INFO_MESSAGE()
422{
423 printMsg("INFO", "$HelpMessage
424EXTRA OPTIONS:
425 -d|-descriptor-template
426 Create XML-descriptor template ./VERSION.xml
427
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400428 -app|-application PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400429 This option allows to specify the application that should be checked
430 for portability to the new library version.
431
432 -static-libs
433 Check static libraries instead of the shared ones. The <libs> section
434 of the XML-descriptor should point to static libraries location.
435
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400436 -cross-gcc|-gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400437 Path to the cross GCC compiler to use instead of the usual (host) GCC.
438
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400439 -cross-prefix|-gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400440 GCC toolchain prefix.
441
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400442 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400443 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400444 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400445
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400446 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400447 Specify 1st library version outside the descriptor. This option is needed
448 if you have prefered an alternative descriptor type (see -d1 option).
449
450 In general case you should specify it in the XML-descriptor:
451 <version>
452 VERSION
453 </version>
454
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400455 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400456 Specify 2nd library version outside the descriptor.
457
458 -s|-strict
459 Treat all compatibility warnings as problems. Add a number of \"Low\"
460 severity problems to the return value of the tool.
461
462 -headers-only
463 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
464 provide a low quality compatibility report with false positives and
465 without detecting of added/removed symbols.
466
467 Alternatively you can write \"none\" word to the <libs> section
468 in the XML-descriptor:
469 <libs>
470 none
471 </libs>
472
473 -objects-only
474 Check $SLIB_TYPE libraries without header files. It is easy to run, but may
475 provide a low quality compatibility report with false positives and
476 without analysis of changes in parameters and data types.
477
478 Alternatively you can write \"none\" word to the <headers> section
479 in the XML-descriptor:
480 <headers>
481 none
482 </headers>
483
484 -check-impl|-check-implementation
485 Compare canonified disassembled binary code of $SLIB_TYPE libraries to
486 detect changes in the implementation. Add \'Problems with Implementation\'
487 section to the report.
488
489 -show-retval
490 Show the symbol's return type in the report.
491
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400492 -symbols-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400493 This option allows to specify a file with a list of symbols (mangled
494 names in C++) that should be checked, other symbols will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400495
496 -skip-symbols PATH
497 The list of symbols that should NOT be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400498
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400499 -headers-list PATH
500 The file with a list of headers, that should be checked/dumped.
501
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400502 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400503 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400504
505 -header NAME
506 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400507
508 -use-dumps
509 Make dumps for two versions of a library and compare dumps. This should
510 increase the performance of the tool and decrease the system memory usage.
511
512 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400513 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400514
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400515 -dump-system NAME -sysroot DIR
516 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400517 create XML descriptors and make ABI dumps for each library. The result
518 set of ABI dumps can be compared (--cmp-systems) with the other one
519 created for other version of operating system in order to check them for
520 compatibility. Do not forget to specify -cross-gcc option if your target
521 system requires some specific version of GCC compiler (different from
522 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400523 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400524
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400525 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400526 The same as the previous option but takes an XML descriptor of the target
527 system as input, where you should describe it:
528
529 /* Primary sections */
530
531 <name>
532 /* Name of the system */
533 </name>
534
535 <headers>
536 /* The list of paths to header files and/or
537 directories with header files, one per line */
538 </headers>
539
540 <libs>
541 /* The list of paths to shared libraries and/or
542 directories with shared libraries, one per line */
543 </libs>
544
545 /* Optional sections */
546
547 <search_headers>
548 /* List of directories to be searched
549 for header files to automatically
550 generate include paths, one per line */
551 </search_headers>
552
553 <search_libs>
554 /* List of directories to be searched
555 for shared libraries to resolve
556 dependencies, one per line */
557 </search_libs>
558
559 <tools>
560 /* List of directories with tools used
561 for analysis (GCC toolchain), one per line */
562 </tools>
563
564 <cross_prefix>
565 /* GCC toolchain prefix.
566 Examples:
567 arm-linux-gnueabi
568 arm-none-symbianelf */
569 </cross_prefix>
570
571 <gcc_options>
572 /* Additional GCC options, one per line */
573 </gcc_options>
574
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400575 -sysinfo DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400576 This option may be used with -dump-system to dump ABI of operating
577 systems and configure the dumping process.
578 Default:
579 modules/Targets/{unix, symbian, windows}
580
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400581 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400582 Compare two system ABI dumps. Create compatibility reports for each
583 library and the common HTML report including the summary of test
584 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400585 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400586
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400587 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400588 The file with a list of libraries, that should be dumped by
589 the -dump-system option or should be checked by the -cmp-systems option.
590
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400591 -ext|-extended
592 If your library A is supposed to be used by other library B and you
593 want to control the ABI of B, then you should enable this option. The
594 tool will check for changes in all data types, even if they are not
595 used by any function in the library A. Such data types are not part
596 of the A library ABI, but may be a part of the ABI of the B library.
597
598 The short scheme is:
599 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
600
601 -q|-quiet
602 Print all messages to the file instead of stdout and stderr.
603 Default path (can be changed by -log-path option):
604 $COMMON_LOG_PATH
605
606 -stdout
607 Print analysis results (compatibility reports and ABI dumps) to stdout
608 instead of creating a file. This would allow piping data to other programs.
609
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400610 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400611 Change format of compatibility report.
612 Formats:
613 htm - HTML format (default)
614 xml - XML format
615
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400616 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400617 Change format of ABI dump.
618 Formats:
619 perl - Data::Dumper format (default)
620 xml - XML format
621
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400622 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400623 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400624
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400625 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400626 Set library language (C or C++). You can use this option if the tool
627 cannot auto-detect a language. This option may be useful for checking
628 C-library headers (--lang=C) in --headers-only or --extended modes.
629
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400630 -binary|-bin|-abi
631 Show \"Binary\" compatibility problems only.
632 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400633 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400634
635 -source|-src|-api
636 Show \"Source\" compatibility problems only.
637 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400638 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400639
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400640OTHER OPTIONS:
641 -test
642 Run internal tests. Create two binary incompatible versions of a sample
643 library and run the tool to check them for compatibility. This option
644 allows to check if the tool works correctly in the current environment.
645
646 -test-dump
647 Test ability to create, read and compare ABI dumps.
648
649 -debug
650 Debugging mode. Print debug info on the screen. Save intermediate
651 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400652 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400653
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400654 Also consider using --dump option for debugging the tool.
655
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400656 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400657 If your header files are written in C language and can be compiled
658 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
659 the tool about this and speedup the analysis.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400660
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400661 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400662 Path to file with the function parameter names. It can be used
663 for improving report view if the library header files have no
664 parameter names. File format:
665
666 func1;param1;param2;param3 ...
667 func2;param1;param2;param3 ...
668 ...
669
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400670 -relpath PATH
671 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400672 for dumping the library ABI (see -dump option).
673
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400674 -relpath1 PATH
675 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400676
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400677 -relpath2 PATH
678 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400679
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400680 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400681 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400682 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400683 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400684
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400685 -sort
686 Enable sorting of data in ABI dumps.
687
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400688 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400689 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400690 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400691 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400692
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400693 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400694 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400695 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400696 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400697
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400698 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400699 Path to \"Source\" compatibility report.
700 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400701 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400702
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400703 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400704 Log path for all messages.
705 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400706 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400707
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400708 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400709 Log path for 1st version of a library.
710 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400711 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400712
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400713 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400714 Log path for 2nd version of a library.
715 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400716 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400717
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400718 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400719 Change logging mode.
720 Modes:
721 w - overwrite old logs (default)
722 a - append old logs
723 n - do not write any logs
724
725 -list-affected
726 Generate file with the list of incompatible
727 symbols beside the HTML compatibility report.
728 Use 'c++filt \@file' command from GNU binutils
729 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400730 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400731 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400732 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400733
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400734 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400735 The component name in the title and summary of the HTML report.
736 Default:
737 library
738
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400739 -l-full|-lib-full NAME
740 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400741 will be displayed a name specified by -l option.
742
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400743 -b|-browse PROGRAM
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400744 Open report(s) in the browser (firefox, opera, etc.).
745
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400746 -open
747 Open report(s) in the default browser.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400748
749 -extra-info DIR
750 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400751
752 -extra-dump
753 Create extended ABI dump containing all symbols
754 from the translation unit.
755
756 -force
757 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400758
759 -tolerance LEVEL
760 Apply a set of heuristics to successfully compile input
761 header files. You can enable several tolerance levels by
762 joining them into one string (e.g. 13, 124, etc.).
763 Levels:
764 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
765 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
766 3 - skip headers that iclude non-Linux headers
767 4 - skip headers included by others
768
769 -tolerant
770 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400771
772 -check
773 Check completeness of the ABI dump.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400774
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400775REPORT:
776 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400777 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400778
779 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400780 logs/LIB_NAME/V1/log.txt
781 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400782
783EXIT CODES:
784 0 - Compatible. The tool has run without any errors.
785 non-zero - Incompatible or the tool has run with errors.
786
787REPORT BUGS TO:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400788 Andrey Ponomarenko <aponomarenko\@rosalab.ru>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400789
790MORE INFORMATION:
791 ".$HomePage{"Wiki"}."
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400792 ".$HomePage{"Dev1"}."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400793}
794
795my $DescriptorTemplate = "
796<?xml version=\"1.0\" encoding=\"utf-8\"?>
797<descriptor>
798
799/* Primary sections */
800
801<version>
802 /* Version of the library */
803</version>
804
805<headers>
806 /* The list of paths to header files and/or
807 directories with header files, one per line */
808</headers>
809
810<libs>
811 /* The list of paths to shared libraries (*.$LIB_EXT) and/or
812 directories with shared libraries, one per line */
813</libs>
814
815/* Optional sections */
816
817<include_paths>
818 /* The list of include paths that will be provided
819 to GCC to compile library headers, one per line.
820 NOTE: If you define this section then the tool
821 will not automatically generate include paths */
822</include_paths>
823
824<add_include_paths>
825 /* The list of include paths that will be added
826 to the automatically generated include paths, one per line */
827</add_include_paths>
828
829<skip_include_paths>
830 /* The list of include paths that will be removed from the
831 list of automatically generated include paths, one per line */
832</skip_include_paths>
833
834<gcc_options>
835 /* Additional GCC options, one per line */
836</gcc_options>
837
838<include_preamble>
839 /* The list of header files that will be
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +0400840 included before other headers, one per line */
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400841</include_preamble>
842
843<defines>
844 /* The list of defines that will be added at the
845 headers compiling stage, one per line:
846 #define A B
847 #define C D */
848</defines>
849
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +0400850<add_namespaces>
851 /* The list of namespaces that should be added to the alanysis
852 if the tool cannot find them automatically, one per line */
853</add_namespaces>
854
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400855<skip_types>
856 /* The list of data types, that
857 should not be checked, one per line */
858</skip_types>
859
860<skip_symbols>
861 /* The list of functions (mangled/symbol names in C++),
862 that should not be checked, one per line */
863</skip_symbols>
864
865<skip_namespaces>
866 /* The list of C++ namespaces, that
867 should not be checked, one per line */
868</skip_namespaces>
869
870<skip_constants>
871 /* The list of constants that should
872 not be checked, one name per line */
873</skip_constants>
874
875<skip_headers>
876 /* The list of header files and/or directories
877 with header files that should not be checked, one per line */
878</skip_headers>
879
880<skip_libs>
881 /* The list of shared libraries and/or directories
882 with shared libraries that should not be checked, one per line */
883</skip_libs>
884
885<skip_including>
886 /* The list of header files, that cannot be included
887 directly (or non-self compiled ones), one per line */
888</skip_including>
889
890<search_headers>
891 /* List of directories to be searched
892 for header files to automatically
893 generate include paths, one per line. */
894</search_headers>
895
896<search_libs>
897 /* List of directories to be searched
898 for shared librariess to resolve
899 dependencies, one per line */
900</search_libs>
901
902<tools>
903 /* List of directories with tools used
904 for analysis (GCC toolchain), one per line */
905</tools>
906
907<cross_prefix>
908 /* GCC toolchain prefix.
909 Examples:
910 arm-linux-gnueabi
911 arm-none-symbianelf */
912</cross_prefix>
913
914</descriptor>";
915
916my %Operator_Indication = (
917 "not" => "~",
918 "assign" => "=",
919 "andassign" => "&=",
920 "orassign" => "|=",
921 "xorassign" => "^=",
922 "or" => "|",
923 "xor" => "^",
924 "addr" => "&",
925 "and" => "&",
926 "lnot" => "!",
927 "eq" => "==",
928 "ne" => "!=",
929 "lt" => "<",
930 "lshift" => "<<",
931 "lshiftassign" => "<<=",
932 "rshiftassign" => ">>=",
933 "call" => "()",
934 "mod" => "%",
935 "modassign" => "%=",
936 "subs" => "[]",
937 "land" => "&&",
938 "lor" => "||",
939 "rshift" => ">>",
940 "ref" => "->",
941 "le" => "<=",
942 "deref" => "*",
943 "mult" => "*",
944 "preinc" => "++",
945 "delete" => " delete",
946 "vecnew" => " new[]",
947 "vecdelete" => " delete[]",
948 "predec" => "--",
949 "postinc" => "++",
950 "postdec" => "--",
951 "plusassign" => "+=",
952 "plus" => "+",
953 "minus" => "-",
954 "minusassign" => "-=",
955 "gt" => ">",
956 "ge" => ">=",
957 "new" => " new",
958 "multassign" => "*=",
959 "divassign" => "/=",
960 "div" => "/",
961 "neg" => "-",
962 "pos" => "+",
963 "memref" => "->*",
964 "compound" => "," );
965
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400966my %UnknownOperator;
967
968my %NodeType= (
969 "array_type" => "Array",
970 "binfo" => "Other",
971 "boolean_type" => "Intrinsic",
972 "complex_type" => "Intrinsic",
973 "const_decl" => "Other",
974 "enumeral_type" => "Enum",
975 "field_decl" => "Other",
976 "function_decl" => "Other",
977 "function_type" => "FunctionType",
978 "identifier_node" => "Other",
979 "integer_cst" => "Other",
980 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400981 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400982 "method_type" => "MethodType",
983 "namespace_decl" => "Other",
984 "parm_decl" => "Other",
985 "pointer_type" => "Pointer",
986 "real_cst" => "Other",
987 "real_type" => "Intrinsic",
988 "record_type" => "Struct",
989 "reference_type" => "Ref",
990 "string_cst" => "Other",
991 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400992 "template_type_parm" => "TemplateParam",
993 "typename_type" => "TypeName",
994 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400995 "tree_list" => "Other",
996 "tree_vec" => "Other",
997 "type_decl" => "Other",
998 "union_type" => "Union",
999 "var_decl" => "Other",
1000 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001001 "nop_expr" => "Other", #
1002 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001003 "offset_type" => "Other" );
1004
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001005my %CppKeywords_C = map {$_=>1} (
1006 # C++ 2003 keywords
1007 "public",
1008 "protected",
1009 "private",
1010 "default",
1011 "template",
1012 "new",
1013 #"asm",
1014 "dynamic_cast",
1015 "auto",
1016 "try",
1017 "namespace",
1018 "typename",
1019 "using",
1020 "reinterpret_cast",
1021 "friend",
1022 "class",
1023 "virtual",
1024 "const_cast",
1025 "mutable",
1026 "static_cast",
1027 "export",
1028 # C++0x keywords
1029 "noexcept",
1030 "nullptr",
1031 "constexpr",
1032 "static_assert",
1033 "explicit",
1034 # cannot be used as a macro name
1035 # as it is an operator in C++
1036 "and",
1037 #"and_eq",
1038 "not",
1039 #"not_eq",
1040 "or"
1041 #"or_eq",
1042 #"bitand",
1043 #"bitor",
1044 #"xor",
1045 #"xor_eq",
1046 #"compl"
1047);
1048
1049my %CppKeywords_F = map {$_=>1} (
1050 "delete",
1051 "catch",
1052 "alignof",
1053 "thread_local",
1054 "decltype",
1055 "typeid"
1056);
1057
1058my %CppKeywords_O = map {$_=>1} (
1059 "bool",
1060 "register",
1061 "inline",
1062 "operator"
1063);
1064
1065my %CppKeywords_A = map {$_=>1} (
1066 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001067 "throw",
1068 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001069);
1070
1071foreach (keys(%CppKeywords_C),
1072keys(%CppKeywords_F),
1073keys(%CppKeywords_O)) {
1074 $CppKeywords_A{$_}=1;
1075}
1076
1077# Header file extensions as described by gcc
1078my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
1079
1080my %IntrinsicMangling = (
1081 "void" => "v",
1082 "bool" => "b",
1083 "wchar_t" => "w",
1084 "char" => "c",
1085 "signed char" => "a",
1086 "unsigned char" => "h",
1087 "short" => "s",
1088 "unsigned short" => "t",
1089 "int" => "i",
1090 "unsigned int" => "j",
1091 "long" => "l",
1092 "unsigned long" => "m",
1093 "long long" => "x",
1094 "__int64" => "x",
1095 "unsigned long long" => "y",
1096 "__int128" => "n",
1097 "unsigned __int128" => "o",
1098 "float" => "f",
1099 "double" => "d",
1100 "long double" => "e",
1101 "__float80" => "e",
1102 "__float128" => "g",
1103 "..." => "z"
1104);
1105
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001106my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
1107
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001108my %StdcxxMangling = (
1109 "3std"=>"St",
1110 "3std9allocator"=>"Sa",
1111 "3std12basic_string"=>"Sb",
1112 "3std12basic_stringIcE"=>"Ss",
1113 "3std13basic_istreamIcE"=>"Si",
1114 "3std13basic_ostreamIcE"=>"So",
1115 "3std14basic_iostreamIcE"=>"Sd"
1116);
1117
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04001118my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001119my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
1120
1121my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001122
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001123my %ConstantSuffix = (
1124 "unsigned int"=>"u",
1125 "long"=>"l",
1126 "unsigned long"=>"ul",
1127 "long long"=>"ll",
1128 "unsigned long long"=>"ull"
1129);
1130
1131my %ConstantSuffixR =
1132reverse(%ConstantSuffix);
1133
1134my %OperatorMangling = (
1135 "~" => "co",
1136 "=" => "aS",
1137 "|" => "or",
1138 "^" => "eo",
1139 "&" => "an",#ad (addr)
1140 "==" => "eq",
1141 "!" => "nt",
1142 "!=" => "ne",
1143 "<" => "lt",
1144 "<=" => "le",
1145 "<<" => "ls",
1146 "<<=" => "lS",
1147 ">" => "gt",
1148 ">=" => "ge",
1149 ">>" => "rs",
1150 ">>=" => "rS",
1151 "()" => "cl",
1152 "%" => "rm",
1153 "[]" => "ix",
1154 "&&" => "aa",
1155 "||" => "oo",
1156 "*" => "ml",#de (deref)
1157 "++" => "pp",#
1158 "--" => "mm",#
1159 "new" => "nw",
1160 "delete" => "dl",
1161 "new[]" => "na",
1162 "delete[]" => "da",
1163 "+=" => "pL",
1164 "+" => "pl",#ps (pos)
1165 "-" => "mi",#ng (neg)
1166 "-=" => "mI",
1167 "*=" => "mL",
1168 "/=" => "dV",
1169 "&=" => "aN",
1170 "|=" => "oR",
1171 "%=" => "rM",
1172 "^=" => "eO",
1173 "/" => "dv",
1174 "->*" => "pm",
1175 "->" => "pt",#rf (ref)
1176 "," => "cm",
1177 "?" => "qu",
1178 "." => "dt",
1179 "sizeof"=> "sz"#st
1180);
1181
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001182my %Intrinsic_Keywords = map {$_=>1} (
1183 "true",
1184 "false",
1185 "_Bool",
1186 "_Complex",
1187 "const",
1188 "int",
1189 "long",
1190 "void",
1191 "short",
1192 "float",
1193 "volatile",
1194 "restrict",
1195 "unsigned",
1196 "signed",
1197 "char",
1198 "double",
1199 "class",
1200 "struct",
1201 "union",
1202 "enum"
1203);
1204
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001205my %GlibcHeader = map {$_=>1} (
1206 "aliases.h",
1207 "argp.h",
1208 "argz.h",
1209 "assert.h",
1210 "cpio.h",
1211 "ctype.h",
1212 "dirent.h",
1213 "envz.h",
1214 "errno.h",
1215 "error.h",
1216 "execinfo.h",
1217 "fcntl.h",
1218 "fstab.h",
1219 "ftw.h",
1220 "glob.h",
1221 "grp.h",
1222 "iconv.h",
1223 "ifaddrs.h",
1224 "inttypes.h",
1225 "langinfo.h",
1226 "limits.h",
1227 "link.h",
1228 "locale.h",
1229 "malloc.h",
1230 "math.h",
1231 "mntent.h",
1232 "monetary.h",
1233 "nl_types.h",
1234 "obstack.h",
1235 "printf.h",
1236 "pwd.h",
1237 "regex.h",
1238 "sched.h",
1239 "search.h",
1240 "setjmp.h",
1241 "shadow.h",
1242 "signal.h",
1243 "spawn.h",
1244 "stdarg.h",
1245 "stdint.h",
1246 "stdio.h",
1247 "stdlib.h",
1248 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001249 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001250 "tar.h",
1251 "termios.h",
1252 "time.h",
1253 "ulimit.h",
1254 "unistd.h",
1255 "utime.h",
1256 "wchar.h",
1257 "wctype.h",
1258 "wordexp.h" );
1259
1260my %GlibcDir = map {$_=>1} (
1261 "arpa",
1262 "bits",
1263 "gnu",
1264 "netinet",
1265 "net",
1266 "nfs",
1267 "rpc",
1268 "sys",
1269 "linux" );
1270
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001271my %WinHeaders = map {$_=>1} (
1272 "dos.h",
1273 "process.h",
1274 "winsock.h",
1275 "config-win.h",
1276 "mem.h",
1277 "windows.h",
1278 "winsock2.h",
1279 "crtdbg.h",
1280 "ws2tcpip.h"
1281);
1282
1283my %ObsoleteHeaders = map {$_=>1} (
1284 "iostream.h",
1285 "fstream.h"
1286);
1287
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001288my %AlienHeaders = map {$_=>1} (
1289 # Solaris
1290 "thread.h",
1291 "sys/atomic.h",
1292 # HPUX
1293 "sys/stream.h",
1294 # Symbian
1295 "AknDoc.h",
1296 # Atari ST
1297 "ext.h",
1298 "tos.h",
1299 # MS-DOS
1300 "alloc.h",
1301 # Sparc
1302 "sys/atomic.h"
1303);
1304
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001305my %ConfHeaders = map {$_=>1} (
1306 "atomic",
1307 "conf.h",
1308 "config.h",
1309 "configure.h",
1310 "build.h",
1311 "setup.h"
1312);
1313
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001314my %LocalIncludes = map {$_=>1} (
1315 "/usr/local/include",
1316 "/usr/local" );
1317
1318my %OS_AddPath=(
1319# These paths are needed if the tool cannot detect them automatically
1320 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001321 "include"=>[
1322 "/Library",
1323 "/Developer/usr/include"
1324 ],
1325 "lib"=>[
1326 "/Library",
1327 "/Developer/usr/lib"
1328 ],
1329 "bin"=>[
1330 "/Developer/usr/bin"
1331 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001332 },
1333 "beos"=>{
1334 # Haiku has GCC 2.95.3 by default
1335 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001336 "include"=>[
1337 "/boot/common",
1338 "/boot/develop"
1339 ],
1340 "lib"=>[
1341 "/boot/common/lib",
1342 "/boot/system/lib",
1343 "/boot/apps"
1344 ],
1345 "bin"=>[
1346 "/boot/common/bin",
1347 "/boot/system/bin",
1348 "/boot/develop/abi"
1349 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001350 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001351);
1352
1353my %Slash_Type=(
1354 "default"=>"/",
1355 "windows"=>"\\"
1356);
1357
1358my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1359
1360# Global Variables
1361my %COMMON_LANGUAGE=(
1362 1 => "C",
1363 2 => "C" );
1364
1365my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001366my $MAX_CPPFILT_FILE_SIZE = 50000;
1367my $CPPFILT_SUPPORT_FILE;
1368
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001369my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1370
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001371my $STDCXX_TESTING = 0;
1372my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001373my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001374
1375my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
1376my $CheckObjectsOnly = $CheckObjectsOnly_Opt;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001377
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001378my $TargetComponent;
1379
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001380my $CheckUndefined = 0;
1381
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001382# Set Target Component Name
1383if($TargetComponent_Opt) {
1384 $TargetComponent = lc($TargetComponent_Opt);
1385}
1386else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001387{ # default: library
1388 # other components: header, system, ...
1389 $TargetComponent = "library";
1390}
1391
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001392my $TOP_REF = "<a style='font-size:11px;' href='#Top'>to the top</a>";
1393
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001394my $SystemRoot;
1395
1396my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001397my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001398my %LOG_PATH;
1399my %DEBUG_PATH;
1400my %Cache;
1401my %LibInfo;
1402my $COMPILE_ERRORS = 0;
1403my %CompilerOptions;
1404my %CheckedDyLib;
1405my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1406
1407# Constants (#defines)
1408my %Constants;
1409my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001410my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001411
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001412# Extra Info
1413my %SymbolHeader;
1414my %KnownLibs;
1415
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001416# Templates
1417my %TemplateInstance;
1418my %BasicTemplate;
1419my %TemplateArg;
1420my %TemplateDecl;
1421my %TemplateMap;
1422
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001423# Types
1424my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001425my %SkipTypes = (
1426 "1"=>{},
1427 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001428my %CheckedTypes;
1429my %TName_Tid;
1430my %EnumMembName_Id;
1431my %NestedNameSpaces = (
1432 "1"=>{},
1433 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001434my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001435my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001436my %ClassVTable;
1437my %ClassVTable_Content;
1438my %VTableClass;
1439my %AllocableClass;
1440my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001441my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001442my %Class_SubClasses;
1443my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001444my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001445my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001446
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001447my %CheckedTypeInfo;
1448
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001449# Typedefs
1450my %Typedef_BaseName;
1451my %Typedef_Tr;
1452my %Typedef_Eq;
1453my %StdCxxTypedef;
1454my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001455my %MissedBase;
1456my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001457my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001458
1459# Symbols
1460my %SymbolInfo;
1461my %tr_name;
1462my %mangled_name_gcc;
1463my %mangled_name;
1464my %SkipSymbols = (
1465 "1"=>{},
1466 "2"=>{} );
1467my %SkipNameSpaces = (
1468 "1"=>{},
1469 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001470my %AddNameSpaces = (
1471 "1"=>{},
1472 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001473my %SymbolsList;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001474my %SkipSymbolsList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001475my %SymbolsList_App;
1476my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001477my %Symbol_Library = (
1478 "1"=>{},
1479 "2"=>{} );
1480my %Library_Symbol = (
1481 "1"=>{},
1482 "2"=>{} );
1483my %DepSymbol_Library = (
1484 "1"=>{},
1485 "2"=>{} );
1486my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001487 "1"=>{},
1488 "2"=>{} );
1489my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001490my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001491my %AddIntParams;
1492my %Interface_Impl;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001493my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001494my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001495my %Library_Needed= (
1496 "1"=>{},
1497 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001498
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001499# Extra Info
1500my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001501my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001502
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001503# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001504my %Include_Preamble = (
1505 "1"=>[],
1506 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001507my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001508my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001509my %HeaderName_Paths;
1510my %Header_Dependency;
1511my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001512my %Include_Paths = (
1513 "1"=>[],
1514 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001515my %INC_PATH_AUTODETECT = (
1516 "1"=>1,
1517 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001518my %Add_Include_Paths = (
1519 "1"=>[],
1520 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001521my %Skip_Include_Paths;
1522my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001523my %Header_ErrorRedirect;
1524my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001525my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001526my %Header_ShouldNotBeUsed;
1527my %RecursiveIncludes;
1528my %Header_Include_Prefix;
1529my %SkipHeaders;
1530my %SkipHeadersList=(
1531 "1"=>{},
1532 "2"=>{} );
1533my %SkipLibs;
1534my %Include_Order;
1535my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001536my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001537my %TUnit_Funcs;
1538my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001539
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001540my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001541 "1"=>0,
1542 "2"=>0 );
1543my %AutoPreambleMode = (
1544 "1"=>0,
1545 "2"=>0 );
1546my %MinGWMode = (
1547 "1"=>0,
1548 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001549my %Cpp0xMode = (
1550 "1"=>0,
1551 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001552
1553# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001554my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001555my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001556my %RegisteredSONAMEs;
1557my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001558
1559# System Objects
1560my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001561my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001562my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001563
1564# System Headers
1565my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001566my @DefaultCppPaths;
1567my @DefaultGccPaths;
1568my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001569my %DefaultCppHeader;
1570my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001571my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001572
1573# Merging
1574my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001575my $Version;
1576my %AddedInt;
1577my %RemovedInt;
1578my %AddedInt_Virt;
1579my %RemovedInt_Virt;
1580my %VirtualReplacement;
1581my %ChangedTypedef;
1582my %CompatRules;
1583my %IncompleteRules;
1584my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001585my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001586my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001587my %ReturnedClass;
1588my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001589my %SourceAlternative;
1590my %SourceAlternative_B;
1591my %SourceReplacement;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001592
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001593# Calling Conventions
1594my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001595 1=>{ "R"=>0, "P"=>0 },
1596 2=>{ "R"=>0, "P"=>0 }
1597);
1598
1599# ABI Dump
1600my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001601
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001602# OS Compliance
1603my %TargetLibs;
1604my %TargetHeaders;
1605
1606# OS Specifics
1607my $OStarget = $OSgroup;
1608my %TargetTools;
1609
1610# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001611my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001612
1613# Recursion locks
1614my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001615my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001616my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001617my @RecurInclude;
1618my @RecurConstant;
1619
1620# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001621my %SystemPaths = (
1622 "include"=>[],
1623 "lib"=>[],
1624 "bin"=>[]
1625);
1626my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001627my $GCC_PATH;
1628
1629# Symbols versioning
1630my %SymVer = (
1631 "1"=>{},
1632 "2"=>{} );
1633
1634# Problem descriptions
1635my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001636my %CompatProblems_Constants;
1637my %CompatProblems_Impl;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001638my %TotalAffected;
1639
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001640# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001641my $ContentID = 1;
1642my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1643my $ContentSpanStart_Affected = "<span class=\"section_affected\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1644my $ContentSpanStart_Info = "<span class=\"section_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1645my $ContentSpanEnd = "</span>\n";
1646my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1647my $ContentDivEnd = "</div>\n";
1648my $Content_Counter = 0;
1649
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001650# Modes
1651my $JoinReport = 1;
1652my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001653
1654sub get_Modules()
1655{
1656 my $TOOL_DIR = get_dirname($0);
1657 if(not $TOOL_DIR)
1658 { # patch for MS Windows
1659 $TOOL_DIR = ".";
1660 }
1661 my @SEARCH_DIRS = (
1662 # tool's directory
1663 abs_path($TOOL_DIR),
1664 # relative path to modules
1665 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001666 # install path
1667 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001668 );
1669 foreach my $DIR (@SEARCH_DIRS)
1670 {
1671 if(not is_abs($DIR))
1672 { # relative path
1673 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1674 }
1675 if(-d $DIR."/modules") {
1676 return $DIR."/modules";
1677 }
1678 }
1679 exitStatus("Module_Error", "can't find modules");
1680}
1681
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001682my %LoadedModules = ();
1683
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001684sub loadModule($)
1685{
1686 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001687 if(defined $LoadedModules{$Name}) {
1688 return;
1689 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001690 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1691 if(not -f $Path) {
1692 exitStatus("Module_Error", "can't access \'$Path\'");
1693 }
1694 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001695 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001696}
1697
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001698sub readModule($$)
1699{
1700 my ($Module, $Name) = @_;
1701 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1702 if(not -f $Path) {
1703 exitStatus("Module_Error", "can't access \'$Path\'");
1704 }
1705 return readFile($Path);
1706}
1707
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001708sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001709{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001710 my $Number = $_[0];
1711 if(not $Number) {
1712 $Number = 1;
1713 }
1714 else {
1715 $Number = int($Number)+1;
1716 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001717 if($Number>3) {
1718 return $Number."th";
1719 }
1720 elsif($Number==1) {
1721 return "1st";
1722 }
1723 elsif($Number==2) {
1724 return "2nd";
1725 }
1726 elsif($Number==3) {
1727 return "3rd";
1728 }
1729 else {
1730 return $Number;
1731 }
1732}
1733
1734sub search_Tools($)
1735{
1736 my $Name = $_[0];
1737 return "" if(not $Name);
1738 if(my @Paths = keys(%TargetTools))
1739 {
1740 foreach my $Path (@Paths)
1741 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001742 if(-f join_P($Path, $Name)) {
1743 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001744 }
1745 if($CrossPrefix)
1746 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001747 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001748 if(-f $Candidate) {
1749 return $Candidate;
1750 }
1751 }
1752 }
1753 }
1754 else {
1755 return "";
1756 }
1757}
1758
1759sub synch_Cmd($)
1760{
1761 my $Name = $_[0];
1762 if(not $GCC_PATH)
1763 { # GCC was not found yet
1764 return "";
1765 }
1766 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001767 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001768 return $Candidate;
1769 }
1770 return "";
1771}
1772
1773sub get_CmdPath($)
1774{
1775 my $Name = $_[0];
1776 return "" if(not $Name);
1777 if(defined $Cache{"get_CmdPath"}{$Name}) {
1778 return $Cache{"get_CmdPath"}{$Name};
1779 }
1780 my %BinUtils = map {$_=>1} (
1781 "c++filt",
1782 "objdump",
1783 "readelf"
1784 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001785 if($BinUtils{$Name} and $GCC_PATH)
1786 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001787 if(my $Dir = get_dirname($GCC_PATH)) {
1788 $TargetTools{$Dir}=1;
1789 }
1790 }
1791 my $Path = search_Tools($Name);
1792 if(not $Path and $OSgroup eq "windows") {
1793 $Path = search_Tools($Name.".exe");
1794 }
1795 if(not $Path and $BinUtils{$Name})
1796 {
1797 if($CrossPrefix)
1798 { # user-defined prefix
1799 $Path = search_Cmd($CrossPrefix."-".$Name);
1800 }
1801 }
1802 if(not $Path and $BinUtils{$Name})
1803 {
1804 if(my $Candidate = synch_Cmd($Name))
1805 { # synch with GCC
1806 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001807 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001808 if(-f $Candidate) {
1809 $Path = $Candidate;
1810 }
1811 }
1812 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001813 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001814 $Path = $Candidate;
1815 }
1816 }
1817 }
1818 if(not $Path) {
1819 $Path = search_Cmd($Name);
1820 }
1821 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001822 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001823 $Path=search_Cmd($Name.".exe");
1824 }
1825 if($Path=~/\s/) {
1826 $Path = "\"".$Path."\"";
1827 }
1828 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1829}
1830
1831sub search_Cmd($)
1832{
1833 my $Name = $_[0];
1834 return "" if(not $Name);
1835 if(defined $Cache{"search_Cmd"}{$Name}) {
1836 return $Cache{"search_Cmd"}{$Name};
1837 }
1838 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1839 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1840 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001841 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001842 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001843 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001844 if(-f $CmdPath)
1845 {
1846 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001847 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001848 }
1849 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1850 }
1851 }
1852 return ($Cache{"search_Cmd"}{$Name} = "");
1853}
1854
1855sub get_CmdPath_Default($)
1856{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001857 return "" if(not $_[0]);
1858 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1859 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001860 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001861 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1862}
1863
1864sub get_CmdPath_Default_I($)
1865{ # search in PATH
1866 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001867 if($Name=~/find/)
1868 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001869 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001870 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001871 }
1872 }
1873 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001874 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001875 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001876 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001877 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001878 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001879 if($OSgroup eq "windows")
1880 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001881 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001882 return $Name;
1883 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001884 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001885 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001886 {
1887 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001888 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001889 }
1890 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001891 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001892}
1893
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001894sub classifyPath($)
1895{
1896 my $Path = $_[0];
1897 if($Path=~/[\*\[]/)
1898 { # wildcard
1899 $Path=~s/\*/.*/g;
1900 $Path=~s/\\/\\\\/g;
1901 return ($Path, "Pattern");
1902 }
1903 elsif($Path=~/[\/\\]/)
1904 { # directory or relative path
1905 return (path_format($Path, $OSgroup), "Path");
1906 }
1907 else {
1908 return ($Path, "Name");
1909 }
1910}
1911
1912sub readDescriptor($$)
1913{
1914 my ($LibVersion, $Content) = @_;
1915 return if(not $LibVersion);
1916 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1917 if(not $Content) {
1918 exitStatus("Error", "$DName is empty");
1919 }
1920 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001921 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001922 }
1923 $Content=~s/\/\*(.|\n)+?\*\///g;
1924 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001925
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001926 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1927 if($TargetVersion{$LibVersion}) {
1928 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1929 }
1930 if(not $Descriptor{$LibVersion}{"Version"}) {
1931 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1932 }
1933 if($Content=~/{RELPATH}/)
1934 {
1935 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1936 $Content =~ s/{RELPATH}/$RelDir/g;
1937 }
1938 else
1939 {
1940 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1941 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1942 }
1943 }
1944
1945 if(not $CheckObjectsOnly_Opt)
1946 {
1947 my $DHeaders = parseTag(\$Content, "headers");
1948 if(not $DHeaders) {
1949 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1950 }
1951 elsif(lc($DHeaders) ne "none")
1952 { # append the descriptor headers list
1953 if($Descriptor{$LibVersion}{"Headers"})
1954 { # multiple descriptors
1955 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
1956 }
1957 else {
1958 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1959 }
1960 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1961 {
1962 if(not -e $Path) {
1963 exitStatus("Access_Error", "can't access \'$Path\'");
1964 }
1965 }
1966 }
1967 }
1968 if(not $CheckHeadersOnly_Opt)
1969 {
1970 my $DObjects = parseTag(\$Content, "libs");
1971 if(not $DObjects) {
1972 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1973 }
1974 elsif(lc($DObjects) ne "none")
1975 { # append the descriptor libraries list
1976 if($Descriptor{$LibVersion}{"Libs"})
1977 { # multiple descriptors
1978 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1979 }
1980 else {
1981 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1982 }
1983 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1984 {
1985 if(not -e $Path) {
1986 exitStatus("Access_Error", "can't access \'$Path\'");
1987 }
1988 }
1989 }
1990 }
1991 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1992 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001993 if(not -d $Path) {
1994 exitStatus("Access_Error", "can't access directory \'$Path\'");
1995 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001996 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001997 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001998 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001999 }
2000 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
2001 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002002 if(not -d $Path) {
2003 exitStatus("Access_Error", "can't access directory \'$Path\'");
2004 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002005 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002006 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002007 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002008 }
2009 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
2010 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002011 if(not -d $Path) {
2012 exitStatus("Access_Error", "can't access directory \'$Path\'");
2013 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002014 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002015 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002016 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002017 $TargetTools{$Path}=1;
2018 }
2019 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
2020 $CrossPrefix = $Prefix;
2021 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002022 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002023 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
2024 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002025 if(not -d $Path) {
2026 exitStatus("Access_Error", "can't access directory \'$Path\'");
2027 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002028 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002029 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002030 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002031 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002032 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002033 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
2034 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002035 if(not -d $Path) {
2036 exitStatus("Access_Error", "can't access directory \'$Path\'");
2037 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002038 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002039 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002040 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002041 }
2042 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002043 { # skip some auto-generated include paths
2044 if(not is_abs($Path))
2045 {
2046 if(my $P = abs_path($Path)) {
2047 $Path = $P;
2048 }
2049 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002050 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002051 }
2052 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002053 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002054 my ($CPath, $Type) = classifyPath($Path);
2055 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002056 }
2057 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002058 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
2059 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002060 if($Option!~/\A\-(Wl|l|L)/)
2061 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002062 $CompilerOptions{$LibVersion} .= " ".$Option;
2063 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002064 }
2065 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
2066 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
2067 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002068 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002069 my ($CPath, $Type) = classifyPath($Path);
2070 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002071 }
2072 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
2073 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
2074 {
2075 my ($CPath, $Type) = classifyPath($Path);
2076 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
2077 }
2078 if(my $DDefines = parseTag(\$Content, "defines"))
2079 {
2080 if($Descriptor{$LibVersion}{"Defines"})
2081 { # multiple descriptors
2082 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
2083 }
2084 else {
2085 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
2086 }
2087 }
2088 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
2089 {
2090 if($Order=~/\A(.+):(.+)\Z/) {
2091 $Include_Order{$LibVersion}{$1} = $2;
2092 }
2093 }
2094 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
2095 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002096 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002097 $SkipTypes{$LibVersion}{$Type_Name} = 1;
2098 }
2099 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
2100 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002101 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002102 $SkipSymbols{$LibVersion}{$Symbol} = 1;
2103 }
2104 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
2105 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
2106 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04002107 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
2108 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
2109 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002110 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
2111 $SkipConstants{$LibVersion}{$Constant} = 1;
2112 }
2113 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
2114 {
2115 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002116 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002117 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
2118 }
2119 else {
2120 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2121 }
2122 }
2123}
2124
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002125sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002126{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002127 my $CodeRef = shift(@_);
2128 my $Tag = shift(@_);
2129 if(not $Tag or not $CodeRef) {
2130 return undef;
2131 }
2132 my $Sp = 0;
2133 if(@_) {
2134 $Sp = shift(@_);
2135 }
2136 my $Start = index(${$CodeRef}, "<$Tag>");
2137 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002138 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002139 my $End = index(${$CodeRef}, "</$Tag>");
2140 if($End!=-1)
2141 {
2142 my $TS = length($Tag)+3;
2143 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2144 substr($Content, 0, $TS-1, ""); # cut start tag
2145 substr($Content, -$TS, $TS, ""); # cut end tag
2146 if(not $Sp)
2147 {
2148 $Content=~s/\A\s+//g;
2149 $Content=~s/\s+\Z//g;
2150 }
2151 if(substr($Content, 0, 1) ne "<") {
2152 $Content = xmlSpecChars_R($Content);
2153 }
2154 return $Content;
2155 }
2156 }
2157 return undef;
2158}
2159
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002160sub getInfo($)
2161{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002162 my $DumpPath = $_[0];
2163 return if(not $DumpPath or not -f $DumpPath);
2164
2165 readTUDump($DumpPath);
2166
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002167 # processing info
2168 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002169
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002170 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002171 setAnonTypedef_All();
2172 }
2173
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002174 getTypeInfo_All();
2175 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002176 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002177 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002178 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002179
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002180 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002181 %LibInfo = ();
2182 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002183 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002184 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002185 %TemplateDecl = ();
2186 %StdCxxTypedef = ();
2187 %MissedTypedef = ();
2188 %Typedef_Tr = ();
2189 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002190 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002191
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002192 # clean cache
2193 delete($Cache{"getTypeAttr"});
2194 delete($Cache{"getTypeDeclId"});
2195
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002196 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002197 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002198 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002199 }
2200 else
2201 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002202 if($BinaryOnly and not $ExtendedCheck)
2203 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002204 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002205 }
2206 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002207 remove_Unused($Version, "Extended");
2208 }
2209 }
2210
2211 if($CheckInfo)
2212 {
2213 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2214 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2215 }
2216
2217 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2218 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002219 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002220 }
2221
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002222 if($Debug) {
2223 # debugMangling($Version);
2224 }
2225}
2226
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002227sub readTUDump($)
2228{
2229 my $DumpPath = $_[0];
2230
2231 open(TU_DUMP, $DumpPath);
2232 local $/ = undef;
2233 my $Content = <TU_DUMP>;
2234 close(TU_DUMP);
2235
2236 unlink($DumpPath);
2237
2238 $Content=~s/\n[ ]+/ /g;
2239 my @Lines = split("\n", $Content);
2240
2241 # clean memory
2242 undef $Content;
2243
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002244 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002245
2246 foreach (0 .. $#Lines)
2247 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002248 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002249 { # get a number and attributes of a node
2250 next if(not $NodeType{$2});
2251 $LibInfo{$Version}{"info_type"}{$1}=$2;
2252 $LibInfo{$Version}{"info"}{$1}=$3;
2253 }
2254
2255 # clean memory
2256 delete($Lines[$_]);
2257 }
2258
2259 # clean memory
2260 undef @Lines;
2261}
2262
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002263sub simplifyConstants()
2264{
2265 foreach my $Constant (keys(%{$Constants{$Version}}))
2266 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002267 if(defined $Constants{$Version}{$Constant}{"Header"})
2268 {
2269 my $Value = $Constants{$Version}{$Constant}{"Value"};
2270 if(defined $EnumConstants{$Version}{$Value}) {
2271 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2272 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002273 }
2274 }
2275}
2276
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002277sub simplifyNames()
2278{
2279 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2280 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002281 if($Typedef_Eq{$Version}{$Base}) {
2282 next;
2283 }
2284 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2285 if($#Translations==0)
2286 {
2287 if(length($Translations[0])<=length($Base)) {
2288 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2289 }
2290 }
2291 else
2292 { # select most appropriate
2293 foreach my $Tr (@Translations)
2294 {
2295 if($Base=~/\A\Q$Tr\E/)
2296 {
2297 $Typedef_Eq{$Version}{$Base} = $Tr;
2298 last;
2299 }
2300 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002301 }
2302 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002303 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002304 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002305 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002306 if(not $TypeName) {
2307 next;
2308 }
2309 next if(index($TypeName,"<")==-1);# template instances only
2310 if($TypeName=~/>(::\w+)+\Z/)
2311 { # skip unused types
2312 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002313 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002314 foreach my $Base (sort {length($b)<=>length($a)}
2315 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002316 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002317 next if(not $Base);
2318 next if(index($TypeName,$Base)==-1);
2319 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002320 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002321 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002322 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2323 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2324 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002325 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002326 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2327 {
2328 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2329 {
2330 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2331 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002332 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002333 }
2334 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002335 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002337 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002338 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002339 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2340 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002341 }
2342}
2343
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002344sub setAnonTypedef_All()
2345{
2346 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2347 {
2348 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2349 {
2350 if(isAnon(getNameByInfo($InfoId))) {
2351 $TypedefToAnon{getTypeId($InfoId)} = 1;
2352 }
2353 }
2354 }
2355}
2356
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002357sub setTemplateParams_All()
2358{
2359 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2360 {
2361 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2362 setTemplateParams($_);
2363 }
2364 }
2365}
2366
2367sub setTemplateParams($)
2368{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002369 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002370 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002371 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002372 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002373 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002374 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002375 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002376 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002377 setTemplateInstParams($_[0], $TmplInst_Id);
2378 }
2379 }
2380
2381 $BasicTemplate{$Version}{$Tid} = $_[0];
2382
2383 if(my $Prms = getTreeAttr_Prms($_[0]))
2384 {
2385 if(my $Valu = getTreeAttr_Valu($Prms))
2386 {
2387 my $Vector = getTreeVec($Valu);
2388 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2389 {
2390 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2391 {
2392 if(my $Name = getNameByInfo($Val))
2393 {
2394 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2395 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2396 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2397 }
2398 else {
2399 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2400 }
2401 }
2402 }
2403 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002404 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002405 }
2406 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002407 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002408 {
2409 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2410 {
2411 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002412 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002413 }
2414 }
2415 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002416}
2417
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002418sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002419{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002420 my ($Tmpl, $Inst) = @_;
2421
2422 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002423 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002424 my ($Params_InfoId, $ElemId) = ();
2425 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2426 $Params_InfoId = $1;
2427 }
2428 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2429 $ElemId = $1;
2430 }
2431 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002432 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002433 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2434 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2435 {
2436 my ($PPos, $PTypeId) = ($1, $2);
2437 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2438 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002439 if($PType eq "template_type_parm") {
2440 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002441 }
2442 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002443 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2444 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002445 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002446 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002447 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002448 else
2449 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002450 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002451 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002452 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002453 }
2454 }
2455 }
2456}
2457
2458sub getTypeDeclId($)
2459{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002460 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002461 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002462 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2463 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2464 }
2465 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2466 {
2467 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2468 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2469 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002470 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002471 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002472 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002473}
2474
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002475sub getTypeInfo_All()
2476{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002477 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002478 { # support for GCC < 4.5
2479 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2480 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2481 # FIXME: check GCC versions
2482 addMissedTypes_Pre();
2483 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002484
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002485 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002486 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002487 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2488 if($IType=~/_type\Z/ and $IType ne "function_type"
2489 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002490 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002491 }
2492 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002493
2494 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002495 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002496 "Name" => "...",
2497 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002498 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002499 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002500 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002501
2502 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002503 { # support for GCC < 4.5
2504 addMissedTypes_Post();
2505 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002506
2507 if($ADD_TMPL_INSTANCES)
2508 {
2509 # templates
2510 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2511 {
2512 if(defined $TemplateMap{$Version}{$Tid}
2513 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2514 {
2515 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2516 {
2517 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2518 {
2519 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2520 {
2521 if(my %MAttr = getTypeAttr($MembTypeId))
2522 {
2523 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2524 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2525 }
2526 }
2527 }
2528 }
2529 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2530 {
2531 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2532 {
2533 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2534
2535 if($NBid ne $Bid)
2536 {
2537 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2538 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2539 }
2540 }
2541 }
2542 }
2543 }
2544 }
2545}
2546
2547sub createType($$)
2548{
2549 my ($Attr, $LibVersion) = @_;
2550 my $NewId = ++$MAX_ID;
2551
2552 $TypeInfo{$Version}{$NewId} = $Attr;
2553 $TName_Tid{$Version}{$Attr->{"Name"}} = $NewId;
2554
2555 return "$NewId";
2556}
2557
2558sub instType($$$)
2559{ # create template instances
2560 my ($Map, $Tid, $LibVersion) = @_;
2561 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2562
2563 foreach my $Key (sort keys(%{$Map}))
2564 {
2565 if(my $Val = $Map->{$Key})
2566 {
2567 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2568
2569 if(defined $Attr->{"NameSpace"}) {
2570 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2571 }
2572 foreach (keys(%{$Attr->{"TParam"}})) {
2573 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2574 }
2575 }
2576 else
2577 { # remove absent
2578 # _Traits, etc.
2579 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
2580 if(defined $Attr->{"NameSpace"})
2581 {
2582 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2583 }
2584 foreach (keys(%{$Attr->{"TParam"}}))
2585 {
2586 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2587 delete($Attr->{"TParam"}{$_});
2588 }
2589 else
2590 {
2591 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2592 }
2593 }
2594 }
2595 }
2596
2597 my $Tmpl = 0;
2598
2599 if(defined $Attr->{"TParam"})
2600 {
2601 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2602 {
2603 my $PName = $Attr->{"TParam"}{$_}{"name"};
2604
2605 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2606 {
2607 my %Base = get_BaseType($PTid, $LibVersion);
2608
2609 if($Base{"Type"} eq "TemplateParam"
2610 or defined $Base{"Template"})
2611 {
2612 $Tmpl = 1;
2613 last
2614 }
2615 }
2616 }
2617 }
2618
2619 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2620 return "$Id";
2621 }
2622 else
2623 {
2624 if(not $Tmpl) {
2625 delete($Attr->{"Template"});
2626 }
2627
2628 my %EMap = ();
2629 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2630 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2631 }
2632 foreach (keys(%{$Map})) {
2633 $EMap{$_} = $Map->{$_};
2634 }
2635
2636 if(defined $Attr->{"BaseType"}) {
2637 $Attr->{"BaseType"} = instType(\%EMap, $Attr->{"BaseType"}, $LibVersion);
2638 }
2639 if(defined $Attr->{"Base"})
2640 {
2641 foreach my $Bid (keys(%{$Attr->{"Base"}}))
2642 {
2643 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2644
2645 if($NBid ne $Bid)
2646 {
2647 %{$Attr->{"Base"}{$NBid}} = %{$Attr->{"Base"}{$Bid}};
2648 delete($Attr->{"Base"}{$Bid});
2649 }
2650 }
2651 }
2652
2653 my $R = createType($Attr, $LibVersion);
2654
2655 if(defined $Attr->{"Memb"})
2656 {
2657 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"Memb"}})) {
2658 $Attr->{"Memb"}{$_}{"type"} = instType(\%EMap, $Attr->{"Memb"}{$_}{"type"}, $LibVersion);
2659 }
2660 }
2661
2662 if(defined $Attr->{"Param"})
2663 {
2664 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"Param"}})) {
2665 $Attr->{"Param"}{$_}{"type"} = instType(\%EMap, $Attr->{"Param"}{$_}{"type"}, $LibVersion);
2666 }
2667 }
2668
2669 if(defined $Attr->{"Return"}) {
2670 $Attr->{"Return"} = instType(\%EMap, $Attr->{"Return"}, $LibVersion);
2671 }
2672
2673 return $R;
2674 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002675}
2676
2677sub addMissedTypes_Pre()
2678{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002679 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002680 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2681 { # detecting missed typedefs
2682 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2683 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002684 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002685 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002686 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002687 if($TypeType eq "Unknown")
2688 { # template_type_parm
2689 next;
2690 }
2691 my $TypeDeclId = getTypeDeclId($TypeId);
2692 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2693 my $TypedefName = getNameByInfo($MissedTDid);
2694 next if(not $TypedefName);
2695 next if($TypedefName eq "__float80");
2696 next if(isAnon($TypedefName));
2697 if(not $TypeDeclId
2698 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002699 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002700 }
2701 }
2702 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002703 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002704 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002705 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002706 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002707 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002708 next;
2709 }
2710 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002711 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002712 if(not $TypedefName) {
2713 next;
2714 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002715 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002716 my %MissedInfo = ( # typedef info
2717 "Name" => $TypedefName,
2718 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002719 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002720 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002721 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002722 my ($H, $L) = getLocation($MissedTDid);
2723 $MissedInfo{"Header"} = $H;
2724 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002725 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002726 { # other types
2727 next;
2728 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002729 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002730 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002731 next;
2732 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002733 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002734 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002735 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002736 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002737 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002738 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002739 next;
2740 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002741 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002742 next;
2743 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002744 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002745 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002746 next;
2747 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002748 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002749 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002750 next;
2751 }
2752 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002753
2754 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2755
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002756 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002757 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002758 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002759 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002760 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002761
2762 # add missed & remove other
2763 $TypeInfo{$Version} = \%AddTypes;
2764 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002765}
2766
2767sub addMissedTypes_Post()
2768{
2769 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2770 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002771 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2772 {
2773 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2774 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2775 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2776 }
2777 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002778 }
2779}
2780
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002781sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002782{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002783 my $TypeId = $_[0];
2784 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2785 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002786 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002787 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002788 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002789}
2790
2791sub getArraySize($$)
2792{
2793 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002794 if(my $Size = getSize($TypeId))
2795 {
2796 my $Elems = $Size/$BYTE_SIZE;
2797 while($BaseName=~s/\s*\[(\d+)\]//) {
2798 $Elems/=$1;
2799 }
2800 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2801 {
2802 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2803 $Elems/=$BasicSize;
2804 }
2805 }
2806 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002807 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002808 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002809}
2810
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002811sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002812{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002813 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002814 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002815 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2816 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002817 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002818 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2819 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2820 if(not $NodeType)
2821 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002822 return ();
2823 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002824 if($NodeType eq "tree_vec")
2825 {
2826 if($Pos!=$#Positions)
2827 { # select last vector of parameters ( ns<P1>::type<P2> )
2828 next;
2829 }
2830 }
2831 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2832 foreach my $P (@Params)
2833 {
2834 if($P eq "") {
2835 return ();
2836 }
2837 elsif($P ne "\@skip\@") {
2838 @TmplParams = (@TmplParams, $P);
2839 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002840 }
2841 }
2842 return @TmplParams;
2843}
2844
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002845sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002846{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002847 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002848 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002849 if(defined $TypeInfo{$Version}{$TypeId}
2850 and $TypeInfo{$Version}{$TypeId}{"Name"})
2851 { # already created
2852 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002853 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002854 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2855 { # incomplete type
2856 return ();
2857 }
2858 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2859
2860 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002861 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002862
2863 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2864 {
2865 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2866 {
2867 if($Info=~/qual[ ]*:/)
2868 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002869 my $NewId = ++$MAX_ID;
2870
2871 $MissedBase{$Version}{$TypeId} = "$NewId";
2872 $MissedBase_R{$Version}{$NewId} = $TypeId;
2873 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2874 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002875 }
2876 }
2877 $TypeAttr{"Type"} = "Typedef";
2878 }
2879 else {
2880 $TypeAttr{"Type"} = getTypeType($TypeId);
2881 }
2882
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002883 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2884 {
2885 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2886 { # local code
2887 return ();
2888 }
2889 }
2890
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002891 if($TypeAttr{"Type"} eq "Unknown") {
2892 return ();
2893 }
2894 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2895 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002896 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002897 if(my $TName = $TypeAttr{"Name"})
2898 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002899 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002900 $TName_Tid{$Version}{$TName} = $TypeId;
2901 return %TypeAttr;
2902 }
2903 else {
2904 return ();
2905 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002906 }
2907 elsif($TypeAttr{"Type"} eq "Array")
2908 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002909 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2910 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002911 return ();
2912 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002913 if(my $Algn = getAlgn($TypeId)) {
2914 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2915 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002916 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002917 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002918 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002919 if(not $BTAttr{"Name"}) {
2920 return ();
2921 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002922 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002923 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002924 if(my $Size = getSize($TypeId)) {
2925 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2926 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002927 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002928 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2929 }
2930 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002931 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002932 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002933 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002934 else
2935 {
2936 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002937 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002938 $TypeAttr{"Name"} = $1."[]".$2;
2939 }
2940 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002941 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002942 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002943 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002944 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002945 if($BTAttr{"Header"}) {
2946 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002947 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002948 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002949 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2950 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002951 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002952 return ();
2953 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002954 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002955 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002956 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002957 if($TypeAttr{"Name"})
2958 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002959 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002960
2961 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2962 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002963 { # NOTE: register only one int: with built-in decl
2964 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2965 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2966 }
2967 }
2968 return %TypeAttr;
2969 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002970 else {
2971 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002972 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002973 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002974 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2975 {
2976 %TypeAttr = getTrivialTypeAttr($TypeId);
2977 if($TypeAttr{"Name"})
2978 {
2979 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2980 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2981 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2982 }
2983 return %TypeAttr;
2984 }
2985 else {
2986 return ();
2987 }
2988 }
2989 elsif($TypeAttr{"Type"} eq "SizeOf")
2990 {
2991 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
2992 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
2993 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
2994 if($TypeAttr{"Name"})
2995 {
2996 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2997 return %TypeAttr;
2998 }
2999 else {
3000 return ();
3001 }
3002 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003003 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003004 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003005 my ($BTid, $BTSpec) = selectBaseType($TypeId);
3006 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003007 return ();
3008 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003009 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003010 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003011 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003012 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003013 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003014 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003015 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003016 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003017 }
3018 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003019 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003020 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003021 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003022 return ();
3023 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003024 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003025 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003026 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003027 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003028 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003029 }
3030 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003031 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003032 {
3033 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003034 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003035 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003036 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003037 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
3038 }
3039 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003040 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003041 }
3042 }
3043 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003044 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003045 }
3046 if($TypeAttr{"Type"} eq "Typedef")
3047 {
3048 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003049
3050 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
3051 return ();
3052 }
3053
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003054 if(isAnon($TypeAttr{"Name"}))
3055 { # anon typedef to anon type: ._N
3056 return ();
3057 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003058
3059 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
3060 { # artificial typedef of "struct X" to "X"
3061 $TypeAttr{"Artificial"} = 1;
3062 }
3063
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003064 if(my $NS = getNameSpace($TypeDeclId))
3065 {
3066 my $TypeName = $TypeAttr{"Name"};
3067 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
3068 { # "some_type" is the typedef to "struct some_type" in C++
3069 if($3) {
3070 $TypeAttr{"Name"} = $3."::".$TypeName;
3071 }
3072 }
3073 else
3074 {
3075 $TypeAttr{"NameSpace"} = $NS;
3076 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003077
3078 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
3079 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
3080 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003081 if($BTAttr{"NameSpace"}
3082 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003083 { # types like "std::fpos<__mbstate_t>" are
3084 # not covered by typedefs in the TU dump
3085 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003086 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3087 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003088 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003089 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003090 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003091 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003092 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003093 }
3094 }
3095 }
3096 }
3097 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003098 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003099 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003100 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003101 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
3102 { # typedef int*const TYPEDEF; // first
3103 # int foo(TYPEDEF p); // const is optimized out
3104 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
3105 if($BTAttr{"Name"}=~/</)
3106 {
3107 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
3108 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3109 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003110 }
3111 }
3112 }
3113 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
3114 }
3115 if(not $TypeAttr{"Size"})
3116 {
3117 if($TypeAttr{"Type"} eq "Pointer") {
3118 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3119 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003120 elsif($BTAttr{"Size"}) {
3121 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003122 }
3123 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003124 if(my $Algn = getAlgn($TypeId)) {
3125 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3126 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003127 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003128 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3129 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003130 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003131 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003132 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003133 { # typedef to "class Class"
3134 # should not be registered in TName_Tid
3135 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3136 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3137 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003138 }
3139 return %TypeAttr;
3140 }
3141}
3142
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003143sub getTreeVec($)
3144{
3145 my %Vector = ();
3146 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3147 {
3148 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3149 { # string length is N-1 because of the null terminator
3150 $Vector{$1} = $2;
3151 }
3152 }
3153 return \%Vector;
3154}
3155
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003156sub get_TemplateParam($$)
3157{
3158 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003159 return () if(not $Type_Id);
3160 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3161 return () if(not $NodeType);
3162 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003163 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003164 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003165 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003166 my $Num = getNodeIntCst($Type_Id);
3167 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003168 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003169 }
3170 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003171 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003172 }
3173 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003174 elsif($NodeType eq "string_cst") {
3175 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003176 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003177 elsif($NodeType eq "tree_vec")
3178 {
3179 my $Vector = getTreeVec($Type_Id);
3180 my @Params = ();
3181 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3182 {
3183 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3184 push(@Params, $P2);
3185 }
3186 }
3187 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003188 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003189 elsif($NodeType eq "parm_decl")
3190 {
3191 (getNameByInfo($Type_Id));
3192 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003193 else
3194 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003195 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003196 my $PName = $ParamAttr{"Name"};
3197 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003198 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003199 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003200 if($PName=~/\>/)
3201 {
3202 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003203 $PName = $Cover;
3204 }
3205 }
3206 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003207 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003208 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3209 # template<typename _Key, typename _Compare = std::less<_Key>
3210 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3211 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3212 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3213 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003214 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003215 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003216 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003217 }
3218}
3219
3220sub cover_stdcxx_typedef($)
3221{
3222 my $TypeName = $_[0];
3223 if(my @Covers = sort {length($a)<=>length($b)}
3224 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3225 { # take the shortest typedef
3226 # FIXME: there may be more than
3227 # one typedefs to the same type
3228 return $Covers[0];
3229 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003230 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003231 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3232 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3233 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003234 if(my $Cover = $Covers[0])
3235 {
3236 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3237 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3238 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003239 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003240 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003241}
3242
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003243sub getNodeIntCst($)
3244{
3245 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003246 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003247 if($EnumMembName_Id{$Version}{$CstId}) {
3248 return $EnumMembName_Id{$Version}{$CstId};
3249 }
3250 elsif((my $Value = getTreeValue($CstId)) ne "")
3251 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003252 if($Value eq "0")
3253 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003254 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003255 return "false";
3256 }
3257 else {
3258 return "0";
3259 }
3260 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003261 elsif($Value eq "1")
3262 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003263 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003264 return "true";
3265 }
3266 else {
3267 return "1";
3268 }
3269 }
3270 else {
3271 return $Value;
3272 }
3273 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003274 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003275}
3276
3277sub getNodeStrCst($)
3278{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003279 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3280 {
3281 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003282 {
3283 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3284 { # string length is N-1 because of the null terminator
3285 return substr($1, 0, $2-1);
3286 }
3287 else
3288 { # identifier_node
3289 return substr($1, 0, $2);
3290 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003291 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003292 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003293 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003294}
3295
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003296sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003297{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003298 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003299 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3300 if($Type eq "FieldPtr") {
3301 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3302 }
3303 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3304 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003305 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003306 if($Type eq "MethodPtr")
3307 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003308 if(my $Size = getSize($TypeId))
3309 {
3310 $Size/=$BYTE_SIZE;
3311 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003312 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003313 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003314 if(my $Algn = getAlgn($TypeId)) {
3315 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003317 # Return
3318 if($Type eq "FieldPtr")
3319 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003320 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003321 if($ReturnAttr{"Name"}) {
3322 $MemPtrName .= $ReturnAttr{"Name"};
3323 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003324 $TypeAttr{"Return"} = $PtrId;
3325 }
3326 else
3327 {
3328 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3329 {
3330 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003331 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3332 if(not $ReturnAttr{"Name"})
3333 { # templates
3334 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003335 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003336 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003337 $TypeAttr{"Return"} = $ReturnTypeId;
3338 }
3339 }
3340 # Class
3341 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3342 {
3343 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003344 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003345 if($Class{"Name"}) {
3346 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3347 }
3348 else {
3349 $MemPtrName .= " (*)";
3350 }
3351 }
3352 else {
3353 $MemPtrName .= " (*)";
3354 }
3355 # Parameters
3356 if($Type eq "FuncPtr"
3357 or $Type eq "MethodPtr")
3358 {
3359 my @ParamTypeName = ();
3360 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3361 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003362 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003363 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003364 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003365 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003366 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3367 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003368 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003369 my $PTypeId = $1;
3370 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003371 if(not $ParamAttr{"Name"})
3372 { # templates (template_type_parm), etc.
3373 return ();
3374 }
3375 if($ParamAttr{"Name"} eq "void") {
3376 last;
3377 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003378 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003379 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003380 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003381 push(@ParamTypeName, $ParamAttr{"Name"});
3382 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003383 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3384 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003385 }
3386 else {
3387 last;
3388 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003389 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003390 else {
3391 last;
3392 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003393 }
3394 }
3395 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3396 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003397 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003398 return %TypeAttr;
3399}
3400
3401sub getTreeTypeName($)
3402{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003403 my $TypeId = $_[0];
3404 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003405 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003406 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003407 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003408 if(my $Name = getNameByInfo($TypeId))
3409 { # bit_size_type
3410 return $Name;
3411 }
3412 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003413 return "unsigned int";
3414 }
3415 else {
3416 return "int";
3417 }
3418 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003419 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003420 return getNameByInfo($1);
3421 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003422 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003423 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003424}
3425
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003426sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003427{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003428 my $Ptd = pointTo($_[0]);
3429 return 0 if(not $Ptd);
3430 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003431 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003432 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3433 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003434 }
3435 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003436 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3437 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003438 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003439 if($InfoT1 eq "pointer_type"
3440 and $InfoT2 eq "function_type") {
3441 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003442 }
3443 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003444 return 0;
3445}
3446
3447sub isMethodPtr($)
3448{
3449 my $Ptd = pointTo($_[0]);
3450 return 0 if(not $Ptd);
3451 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3452 {
3453 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3454 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3455 and $Info=~/ ptrmem /) {
3456 return 1;
3457 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003458 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003459 return 0;
3460}
3461
3462sub isFieldPtr($)
3463{
3464 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3465 {
3466 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3467 and $Info=~/ ptrmem /) {
3468 return 1;
3469 }
3470 }
3471 return 0;
3472}
3473
3474sub pointTo($)
3475{
3476 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3477 {
3478 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3479 return $1;
3480 }
3481 }
3482 return "";
3483}
3484
3485sub getTypeTypeByTypeId($)
3486{
3487 my $TypeId = $_[0];
3488 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3489 {
3490 my $NType = $NodeType{$TType};
3491 if($NType eq "Intrinsic") {
3492 return $NType;
3493 }
3494 elsif(isFuncPtr($TypeId)) {
3495 return "FuncPtr";
3496 }
3497 elsif(isMethodPtr($TypeId)) {
3498 return "MethodPtr";
3499 }
3500 elsif(isFieldPtr($TypeId)) {
3501 return "FieldPtr";
3502 }
3503 elsif($NType ne "Other") {
3504 return $NType;
3505 }
3506 }
3507 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003508}
3509
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003510my %UnQual = (
3511 "r"=>"restrict",
3512 "v"=>"volatile",
3513 "c"=>"const",
3514 "cv"=>"const volatile"
3515);
3516
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003517sub getQual($)
3518{
3519 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003520 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3521 {
3522 my ($Qual, $To) = ();
3523 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3524 $Qual = $UnQual{$1};
3525 }
3526 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3527 $To = $1;
3528 }
3529 if($Qual and $To) {
3530 return ($Qual, $To);
3531 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003532 }
3533 return ();
3534}
3535
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003536sub getQualType($)
3537{
3538 if($_[0] eq "const volatile") {
3539 return "ConstVolatile";
3540 }
3541 return ucfirst($_[0]);
3542}
3543
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003544sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003545{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003546 my $TypeId = $_[0];
3547 my $TypeDeclId = getTypeDeclId($TypeId);
3548 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003549 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003550 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3551 return "Typedef";
3552 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003553 }
3554 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3555 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003556 if(($Qual or $To) and $TypeDeclId
3557 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003558 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003559 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003560 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003561 elsif(not $MissedBase_R{$Version}{$TypeId}
3562 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003563 return "Typedef";
3564 }
3565 elsif($Qual)
3566 { # qualified types
3567 return getQualType($Qual);
3568 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003569
3570 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3571 { # typedef struct { ... } name
3572 $TypeTypedef{$Version}{$TypeId} = $1;
3573 }
3574
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003575 my $TypeType = getTypeTypeByTypeId($TypeId);
3576 if($TypeType eq "Struct")
3577 {
3578 if($TypeDeclId
3579 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3580 return "Template";
3581 }
3582 }
3583 return $TypeType;
3584}
3585
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003586sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003587{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003588 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003589 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003590 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3591 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3592 return 0;
3593 }
3594 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3595 {
3596 my $TDid = getTypeDeclId($_[0]);
3597 if(getNameByInfo($TDid)
3598 and $Info=~/unql[ ]*:[ ]*\@(\d+) /
3599 and getTypeId($TDid) eq $_[0]) {
3600 return $1;
3601 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003602 }
3603 }
3604 return 0;
3605}
3606
3607sub selectBaseType($)
3608{
3609 my $TypeId = $_[0];
3610 if(defined $MissedTypedef{$Version}{$TypeId})
3611 { # add missed typedefs
3612 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3613 return ($TypeId, "");
3614 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003615 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003616 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3617 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003618
3619 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3620 my $MB = $MissedBase{$Version}{$TypeId};
3621
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003622 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003623 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003624 and (getTypeId($1) ne $TypeId)
3625 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003626 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003627 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003628 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003629 elsif($MB)
3630 { # add base
3631 return ($MB, "");
3632 }
3633 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003634 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003635 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003636 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003637 elsif($Qual or $To)
3638 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003639 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003640 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003641 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003642 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003643 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003644 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003645 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003646 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003647 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003648 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003649 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003650 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003652 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003653 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003654 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003655 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003656 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003657 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003658 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003659
3660 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003661}
3662
3663sub getSymbolInfo_All()
3664{
3665 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3666 { # reverse order
3667 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003668 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003669 }
3670 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003671
3672 if($ADD_TMPL_INSTANCES)
3673 {
3674 # templates
3675 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3676 {
3677 my %Map = ();
3678
3679 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3680 {
3681 if(defined $TemplateMap{$Version}{$ClassId})
3682 {
3683 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3684 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3685 }
3686 }
3687 }
3688
3689 if(defined $TemplateMap{$Version}{$Sid})
3690 {
3691 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3692 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3693 }
3694 }
3695
3696 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3697 {
3698 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3699 {
3700 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3701 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3702 }
3703 }
3704 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3705 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3706 }
3707 }
3708 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003709}
3710
3711sub getVarInfo_All()
3712{
3713 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3714 { # reverse order
3715 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003716 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003717 }
3718 }
3719}
3720
3721sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003722 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003723}
3724
3725sub getVarInfo($)
3726{
3727 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003728 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003729 {
3730 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3731 if($NSInfoType and $NSInfoType eq "function_decl") {
3732 return;
3733 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003734 }
3735 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3736 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3737 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3738 delete($SymbolInfo{$Version}{$InfoId});
3739 return;
3740 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003741 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003742 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003743 delete($SymbolInfo{$Version}{$InfoId});
3744 return;
3745 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003746 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3747 delete($SymbolInfo{$Version}{$InfoId});
3748 return;
3749 }
3750 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003751 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3752 {
3753 if($OSgroup eq "windows")
3754 { # cut the offset
3755 $MnglName=~s/\@\d+\Z//g;
3756 }
3757 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3758 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003759 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003760 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003761 { # validate mangled name
3762 delete($SymbolInfo{$Version}{$InfoId});
3763 return;
3764 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003765 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003766 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003767 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003768 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003769 }
3770 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3771 { # non-public global data
3772 delete($SymbolInfo{$Version}{$InfoId});
3773 return;
3774 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003775 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003776 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003777 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003778 if(not defined $TypeInfo{$Version}{$Rid}
3779 or not $TypeInfo{$Version}{$Rid}{"Name"})
3780 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003781 delete($SymbolInfo{$Version}{$InfoId});
3782 return;
3783 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003784 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3785 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003786 if(defined $Val) {
3787 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3788 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003789 }
3790 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003791 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3792 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003793 if(not defined $TypeInfo{$Version}{$ClassId}
3794 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3795 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003796 delete($SymbolInfo{$Version}{$InfoId});
3797 return;
3798 }
3799 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003800 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3801 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003802 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003803 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003804 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003805 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003806 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003807 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003808 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003809 if(not $CheckHeadersOnly)
3810 {
3811 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3812 {
3813 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3814 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3815 {
3816 if(link_symbol($ShortName, $Version, "-Deps"))
3817 { # "const" global data is mangled as _ZL... in the TU dump
3818 # but not mangled when compiling a C shared library
3819 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3820 }
3821 }
3822 }
3823 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003824 if($COMMON_LANGUAGE{$Version} eq "C++")
3825 {
3826 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3827 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003828 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003829 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3830 }
3831 }
3832 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3833 { # try to mangle symbol (link with libraries)
3834 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3835 }
3836 if($OStarget eq "windows")
3837 {
3838 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3839 { # link MS C++ symbols from library with GCC symbols from headers
3840 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3841 }
3842 }
3843 }
3844 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3845 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3846 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003847 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3848 {
3849 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3850 { # non-target symbols
3851 delete($SymbolInfo{$Version}{$InfoId});
3852 return;
3853 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003854 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003855 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3856 {
3857 if(defined $MissedTypedef{$Version}{$Rid})
3858 {
3859 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3860 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3861 }
3862 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003863 }
3864 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003865 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003866 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3867 }
3868 if($ShortName=~/\A(_Z|\?)/) {
3869 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3870 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003871
3872 if($ExtraDump) {
3873 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3874 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003875}
3876
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003877sub isConstType($$)
3878{
3879 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003880 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003881 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003882 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003883 }
3884 return ($Base{"Type"} eq "Const");
3885}
3886
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003887sub getTrivialName($$)
3888{
3889 my ($TypeInfoId, $TypeId) = @_;
3890 my %TypeAttr = ();
3891 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3892 if(not $TypeAttr{"Name"}) {
3893 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3894 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003895 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003896 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003897 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003898 if(isAnon($TypeAttr{"Name"}))
3899 {
3900 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003901 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003902 { # searching for a first not anon scope
3903 if($NSId eq $NameSpaceId) {
3904 last;
3905 }
3906 else
3907 {
3908 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3909 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003910 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003911 last;
3912 }
3913 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003914 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003915 }
3916 }
3917 else
3918 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003919 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003920 {
3921 if($NameSpaceId ne $TypeId) {
3922 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3923 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003924 }
3925 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003926 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003927 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3928 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003929 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003930 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003931 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003932 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003933 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003934 if($TypeAttr{"NameSpace"}) {
3935 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3936 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003937 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003938 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3939 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003940 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003941 my @TParams = getTParams($TypeId, "Type");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003942 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003943 }
3944 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3945}
3946
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003947sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003948{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003949 my $TypeId = $_[0];
3950 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003951
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003952 my %TypeAttr = ();
3953
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003954 if($TemplateDecl{$Version}{$TypeId})
3955 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003956 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003957 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003958
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003959 setTypeAccess($TypeId, \%TypeAttr);
3960 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3961 if(isBuiltIn($TypeAttr{"Header"}))
3962 {
3963 delete($TypeAttr{"Header"});
3964 delete($TypeAttr{"Line"});
3965 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003966 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003967 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3968 if(not $TypeAttr{"Name"}) {
3969 return ();
3970 }
3971 if(not $TypeAttr{"NameSpace"}) {
3972 delete($TypeAttr{"NameSpace"});
3973 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003974
3975 my $Tmpl = undef;
3976
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003977 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003978 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003979 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3980
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003981 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003982 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003983 foreach my $Pos (0 .. $#TParams)
3984 {
3985 my $Val = $TParams[$Pos];
3986 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
3987
3988 if(not defined $TypeAttr{"Template"})
3989 {
3990 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
3991
3992 if($Base{"Type"} eq "TemplateParam"
3993 or defined $Base{"Template"}) {
3994 $TypeAttr{"Template"} = 1;
3995 }
3996 }
3997
3998 if($Tmpl)
3999 {
4000 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
4001 {
4002 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
4003
4004 if($Val eq $Arg) {
4005 $TypeAttr{"Template"} = 1;
4006 }
4007 }
4008 }
4009 }
4010
4011 if($Tmpl)
4012 {
4013 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
4014 {
4015 if($Pos>$#TParams)
4016 {
4017 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
4018 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
4019 }
4020 }
4021 }
4022 }
4023
4024 if($ADD_TMPL_INSTANCES)
4025 {
4026 if(not getTreeAttr_Flds($TypeId))
4027 {
4028 if($Tmpl)
4029 {
4030 if(my $MainInst = getTreeAttr_Type($Tmpl))
4031 {
4032 if(my $Flds = getTreeAttr_Flds($MainInst)) {
4033 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
4034 }
4035 if(my $Binf = getTreeAttr_Binf($MainInst)) {
4036 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
4037 }
4038 }
4039 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004040 }
4041 }
4042 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004043
4044 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
4045
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004046 if(my $Size = getSize($TypeId))
4047 {
4048 $Size = $Size/$BYTE_SIZE;
4049 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004050 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004051 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004052 {
4053 if($ExtraDump)
4054 {
4055 if(not defined $TypeAttr{"Memb"}
4056 and not $Tmpl)
4057 { # declaration only
4058 $TypeAttr{"Forward"} = 1;
4059 }
4060 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004061 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004062
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004063 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004064 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004065 {
4066 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004067 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004068 }
4069 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004070 or $TypeAttr{"Type"} eq "Class")
4071 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004072 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004073 if($Skip) {
4074 return ();
4075 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004076 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004077 if(my $Algn = getAlgn($TypeId)) {
4078 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
4079 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004080 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004081
4082 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
4083 {
4084 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004085 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004086 {
4087 if(not isAnon($TypeAttr{"Name"})) {
4088 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
4089 }
4090 }
4091 }
4092
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004093 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004094 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4095 {
4096 my @Entries = split(/\n/, $VTable);
4097 foreach (1 .. $#Entries)
4098 {
4099 my $Entry = $Entries[$_];
4100 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004101 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004102 }
4103 }
4104 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004105
4106 if($TypeAttr{"Type"} eq "Enum")
4107 {
4108 if(not $TypeAttr{"NameSpace"})
4109 {
4110 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4111 {
4112 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004113 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004114 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004115 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004116 "Header"=>$TypeAttr{"Header"}
4117 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004118 if(isAnon($TypeAttr{"Name"}))
4119 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004120 if($ExtraDump
4121 or is_target_header($TypeAttr{"Header"}, $Version))
4122 {
4123 %{$Constants{$Version}{$MName}} = (
4124 "Value" => $MVal,
4125 "Header" => $TypeAttr{"Header"}
4126 );
4127 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004128 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004129 }
4130 }
4131 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004132 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004133 {
4134 if(defined $TypedefToAnon{$TypeId}) {
4135 $TypeAttr{"AnonTypedef"} = 1;
4136 }
4137 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004138
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004139 return %TypeAttr;
4140}
4141
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004142sub simplifyVTable($)
4143{
4144 my $Content = $_[0];
4145 if($Content=~s/ \[with (.+)]//)
4146 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4147 if(my @Elems = separate_Params($1, 0, 0))
4148 {
4149 foreach my $Elem (@Elems)
4150 {
4151 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4152 {
4153 my ($Arg, $Val) = ($1, $2);
4154
4155 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4156 $Content=~s/,\s*$Arg\b//g;
4157 }
4158 else {
4159 $Content=~s/\b$Arg\b/$Val/g;
4160 }
4161 }
4162 }
4163 }
4164 }
4165
4166 return $Content;
4167}
4168
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004169sub detect_lang($)
4170{
4171 my $TypeId = $_[0];
4172 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004173 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004174 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004175 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4176 }
4177 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004178 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004179 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004180 while($Fncs)
4181 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004182 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004183 return 1;
4184 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004185 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004186 }
4187 }
4188 return 0;
4189}
4190
4191sub setSpec($$)
4192{
4193 my ($TypeId, $TypeAttr) = @_;
4194 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4195 if($Info=~/\s+spec\s+/) {
4196 $TypeAttr->{"Spec"} = 1;
4197 }
4198}
4199
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004200sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004201{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004202 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004203 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004204 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004205 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004206 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004207 my $Pos = 0;
4208 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4209 {
4210 my ($Access, $BInfoId) = ($1, $2);
4211 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004212 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4213 if(not $CType or $CType eq "template_type_parm"
4214 or $CType eq "typename_type")
4215 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004216 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004217 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004218 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004219 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004220 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4221 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004222 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004223 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4224 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004225 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004226 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004227 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004228 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4229 }
4230 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004231 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004232 }
4233 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004234 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004235}
4236
4237sub getBinfClassId($)
4238{
4239 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
4240 $Info=~/type[ ]*:[ ]*@(\d+) /;
4241 return $1;
4242}
4243
4244sub unmangledFormat($$)
4245{
4246 my ($Name, $LibVersion) = @_;
4247 $Name = uncover_typedefs($Name, $LibVersion);
4248 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4249 $Name=~s/\(\w+\)(\d)/$1/;
4250 return $Name;
4251}
4252
4253sub modelUnmangled($$)
4254{
4255 my ($InfoId, $Compiler) = @_;
4256 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4257 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4258 }
4259 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4260 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4261 $PureSignature = "~".$PureSignature;
4262 }
4263 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4264 {
4265 my (@Params, @ParamTypes) = ();
4266 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4267 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4268 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4269 }
4270 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4271 { # checking parameters
4272 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004273 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004274 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004275 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004276 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004277 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004278 }
4279 @ParamTypes = (@ParamTypes, $PTName);
4280 }
4281 if(@ParamTypes) {
4282 $PureSignature .= "(".join(", ", @ParamTypes).")";
4283 }
4284 else
4285 {
4286 if($Compiler eq "MSVC")
4287 {
4288 $PureSignature .= "(void)";
4289 }
4290 else
4291 { # GCC
4292 $PureSignature .= "()";
4293 }
4294 }
4295 $PureSignature = delete_keywords($PureSignature);
4296 }
4297 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4298 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004299 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004300 $PureSignature = $ClassName."::".$PureSignature;
4301 }
4302 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4303 $PureSignature = $NS."::".$PureSignature;
4304 }
4305 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4306 $PureSignature .= " const";
4307 }
4308 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4309 $PureSignature .= " volatile";
4310 }
4311 my $ShowReturn = 0;
4312 if($Compiler eq "MSVC"
4313 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4314 {
4315 $ShowReturn=1;
4316 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004317 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4318 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004319 {
4320 $ShowReturn=1;
4321 }
4322 if($ShowReturn)
4323 { # mangled names for template function specializations include return value
4324 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4325 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004326 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004327 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4328 $PureSignature = $ReturnName." ".$PureSignature;
4329 }
4330 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004331 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004332}
4333
4334sub mangle_symbol($$$)
4335{ # mangling for simple methods
4336 # see gcc-4.6.0/gcc/cp/mangle.c
4337 my ($InfoId, $LibVersion, $Compiler) = @_;
4338 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4339 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4340 }
4341 my $Mangled = "";
4342 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004343 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004344 }
4345 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004346 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004347 }
4348 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4349}
4350
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004351sub mangle_symbol_MSVC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004352{
4353 my ($InfoId, $LibVersion) = @_;
4354 return "";
4355}
4356
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004357sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004358{ # see gcc-4.6.0/gcc/cp/mangle.c
4359 my ($InfoId, $LibVersion) = @_;
4360 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004361 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004362 my %Repl = ();# SN_ replacements
4363 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4364 {
4365 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4366 if($MangledClass!~/\AN/) {
4367 $MangledClass = "N".$MangledClass;
4368 }
4369 else {
4370 $MangledClass=~s/E\Z//;
4371 }
4372 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4373 $MangledClass=~s/\AN/NV/;
4374 }
4375 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4376 $MangledClass=~s/\AN/NK/;
4377 }
4378 $Mangled .= $MangledClass;
4379 }
4380 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4381 { # mangled by name due to the absence of structured info
4382 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4383 if($MangledNS!~/\AN/) {
4384 $MangledNS = "N".$MangledNS;
4385 }
4386 else {
4387 $MangledNS=~s/E\Z//;
4388 }
4389 $Mangled .= $MangledNS;
4390 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004391 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004392 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004393 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004394 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004395 foreach (@TPos) {
4396 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4397 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004398 }
4399 elsif($TmplParams)
4400 { # remangling mode
4401 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004402 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004403 }
4404 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4405 $Mangled .= "C1";
4406 }
4407 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4408 $Mangled .= "D0";
4409 }
4410 elsif($ShortName)
4411 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004412 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4413 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004414 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004415 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004416 { # "const" global data is mangled as _ZL...
4417 $Mangled .= "L";
4418 }
4419 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004420 if($ShortName=~/\Aoperator(\W.*)\Z/)
4421 {
4422 my $Op = $1;
4423 $Op=~s/\A[ ]+//g;
4424 if(my $OpMngl = $OperatorMangling{$Op}) {
4425 $Mangled .= $OpMngl;
4426 }
4427 else { # conversion operator
4428 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4429 }
4430 }
4431 else {
4432 $Mangled .= length($ShortName).$ShortName;
4433 }
4434 if(@TParams)
4435 { # templates
4436 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004437 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004438 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4439 }
4440 $Mangled .= "E";
4441 }
4442 if(not $ClassId and @TParams) {
4443 add_substitution($ShortName, \%Repl, 0);
4444 }
4445 }
4446 if($ClassId or $NameSpace) {
4447 $Mangled .= "E";
4448 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004449 if(@TParams)
4450 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004451 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004452 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4453 }
4454 }
4455 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4456 {
4457 my @Params = ();
4458 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4459 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4460 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4461 }
4462 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4463 { # checking parameters
4464 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4465 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4466 }
4467 if(not @Params) {
4468 $Mangled .= "v";
4469 }
4470 }
4471 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4472 $Mangled = write_stdcxx_substitution($Mangled);
4473 if($Mangled eq "_Z") {
4474 return "";
4475 }
4476 return $Mangled;
4477}
4478
4479sub correct_incharge($$$)
4480{
4481 my ($InfoId, $LibVersion, $Mangled) = @_;
4482 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4483 {
4484 if($MangledNames{$LibVersion}{$Mangled}) {
4485 $Mangled=~s/C1E/C2E/;
4486 }
4487 }
4488 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4489 {
4490 if($MangledNames{$LibVersion}{$Mangled}) {
4491 $Mangled=~s/D0E/D1E/;
4492 }
4493 if($MangledNames{$LibVersion}{$Mangled}) {
4494 $Mangled=~s/D1E/D2E/;
4495 }
4496 }
4497 return $Mangled;
4498}
4499
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004500sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004501{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004502 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004503 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004504 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004505 return $Name;
4506 }
4507 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004508 while(my $CPos = find_center($TParams, "<"))
4509 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004510 $TParams = substr($TParams, $CPos);
4511 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004512 if($TParams=~s/\A<(.+)>\Z/$1/) {
4513 $Name=~s/<\Q$TParams\E>\Z//;
4514 }
4515 else
4516 { # error
4517 $TParams = "";
4518 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004519 return ($Name, $TParams);
4520}
4521
4522sub get_sub_ns($)
4523{
4524 my $Name = $_[0];
4525 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004526 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004527 {
4528 push(@NS, substr($Name, 0, $CPos));
4529 $Name = substr($Name, $CPos);
4530 $Name=~s/\A:://;
4531 }
4532 return (join("::", @NS), $Name);
4533}
4534
4535sub mangle_ns($$$)
4536{
4537 my ($Name, $LibVersion, $Repl) = @_;
4538 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4539 {
4540 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4541 $Mangled=~s/\AN(.+)E\Z/$1/;
4542 return $Mangled;
4543
4544 }
4545 else
4546 {
4547 my ($MangledNS, $SubNS) = ("", "");
4548 ($SubNS, $Name) = get_sub_ns($Name);
4549 if($SubNS) {
4550 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4551 }
4552 $MangledNS .= length($Name).$Name;
4553 add_substitution($MangledNS, $Repl, 0);
4554 return $MangledNS;
4555 }
4556}
4557
4558sub mangle_param($$$)
4559{
4560 my ($PTid, $LibVersion, $Repl) = @_;
4561 my ($MPrefix, $Mangled) = ("", "");
4562 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004563 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004564 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004565 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004566 if(not $BaseType_Name) {
4567 return "";
4568 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004569 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004570 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004571 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4572 while($Suffix=~/(&|\*|const)\Z/)
4573 {
4574 if($Suffix=~s/[ ]*&\Z//) {
4575 $MPrefix .= "R";
4576 }
4577 if($Suffix=~s/[ ]*\*\Z//) {
4578 $MPrefix .= "P";
4579 }
4580 if($Suffix=~s/[ ]*const\Z//)
4581 {
4582 if($MPrefix=~/R|P/
4583 or $Suffix=~/&|\*/) {
4584 $MPrefix .= "K";
4585 }
4586 }
4587 if($Suffix=~s/[ ]*volatile\Z//) {
4588 $MPrefix .= "V";
4589 }
4590 #if($Suffix=~s/[ ]*restrict\Z//) {
4591 #$MPrefix .= "r";
4592 #}
4593 }
4594 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4595 $Mangled .= $Token;
4596 }
4597 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4598 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004599 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004600 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004601 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004602 foreach (@TPos) {
4603 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4604 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004605 }
4606 elsif($TmplParams)
4607 { # remangling mode
4608 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004609 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004610 }
4611 my $MangledNS = "";
4612 my ($SubNS, $SName) = get_sub_ns($ShortName);
4613 if($SubNS) {
4614 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4615 }
4616 $MangledNS .= length($SName).$SName;
4617 if(@TParams) {
4618 add_substitution($MangledNS, $Repl, 0);
4619 }
4620 $Mangled .= "N".$MangledNS;
4621 if(@TParams)
4622 { # templates
4623 $Mangled .= "I";
4624 foreach my $TParam (@TParams) {
4625 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4626 }
4627 $Mangled .= "E";
4628 }
4629 $Mangled .= "E";
4630 }
4631 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4632 {
4633 if($BaseType{"Type"} eq "MethodPtr") {
4634 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4635 }
4636 else {
4637 $Mangled .= "PF";
4638 }
4639 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4640 my @Params = keys(%{$BaseType{"Param"}});
4641 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4642 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4643 }
4644 if(not @Params) {
4645 $Mangled .= "v";
4646 }
4647 $Mangled .= "E";
4648 }
4649 elsif($BaseType{"Type"} eq "FieldPtr")
4650 {
4651 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4652 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4653 }
4654 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4655 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4656 {
4657 if($Mangled eq $Optimized)
4658 {
4659 if($ShortName!~/::/)
4660 { # remove "N ... E"
4661 if($MPrefix) {
4662 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4663 }
4664 else {
4665 $Mangled=~s/\AN(.+)E\Z/$1/g;
4666 }
4667 }
4668 }
4669 else {
4670 $Mangled = $Optimized;
4671 }
4672 }
4673 add_substitution($Mangled, $Repl, 1);
4674 return $Mangled;
4675}
4676
4677sub mangle_template_param($$$)
4678{ # types + literals
4679 my ($TParam, $LibVersion, $Repl) = @_;
4680 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4681 return mangle_param($TPTid, $LibVersion, $Repl);
4682 }
4683 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4684 { # class_name<1u>::method(...)
4685 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4686 }
4687 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4688 { # class_name<(signed char)1>::method(...)
4689 return "L".$IntrinsicMangling{$1}.$2."E";
4690 }
4691 elsif($TParam eq "true")
4692 { # class_name<true>::method(...)
4693 return "Lb1E";
4694 }
4695 elsif($TParam eq "false")
4696 { # class_name<true>::method(...)
4697 return "Lb0E";
4698 }
4699 else { # internal error
4700 return length($TParam).$TParam;
4701 }
4702}
4703
4704sub add_substitution($$$)
4705{
4706 my ($Value, $Repl, $Rec) = @_;
4707 if($Rec)
4708 { # subtypes
4709 my @Subs = ($Value);
4710 while($Value=~s/\A(R|P|K)//) {
4711 push(@Subs, $Value);
4712 }
4713 foreach (reverse(@Subs)) {
4714 add_substitution($_, $Repl, 0);
4715 }
4716 return;
4717 }
4718 return if($Value=~/\AS(\d*)_\Z/);
4719 $Value=~s/\AN(.+)E\Z/$1/g;
4720 return if(defined $Repl->{$Value});
4721 return if(length($Value)<=1);
4722 return if($StdcxxMangling{$Value});
4723 # check for duplicates
4724 my $Base = $Value;
4725 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4726 {
4727 my $Num = $Repl->{$Type};
4728 my $Replace = macro_mangle($Num);
4729 $Base=~s/\Q$Replace\E/$Type/;
4730 }
4731 if(my $OldNum = $Repl->{$Base})
4732 {
4733 $Repl->{$Value} = $OldNum;
4734 return;
4735 }
4736 my @Repls = sort {$b<=>$a} values(%{$Repl});
4737 if(@Repls) {
4738 $Repl->{$Value} = $Repls[0]+1;
4739 }
4740 else {
4741 $Repl->{$Value} = -1;
4742 }
4743 # register duplicates
4744 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004745 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004746 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4747 {
4748 next if($Base eq $Type);
4749 my $Num = $Repl->{$Type};
4750 my $Replace = macro_mangle($Num);
4751 $Base=~s/\Q$Type\E/$Replace/;
4752 $Repl->{$Base} = $Repl->{$Value};
4753 }
4754}
4755
4756sub macro_mangle($)
4757{
4758 my $Num = $_[0];
4759 if($Num==-1) {
4760 return "S_";
4761 }
4762 else
4763 {
4764 my $Code = "";
4765 if($Num<10)
4766 { # S0_, S1_, S2_, ...
4767 $Code = $Num;
4768 }
4769 elsif($Num>=10 and $Num<=35)
4770 { # SA_, SB_, SC_, ...
4771 $Code = chr(55+$Num);
4772 }
4773 else
4774 { # S10_, S11_, S12_
4775 $Code = $Num-26; # 26 is length of english alphabet
4776 }
4777 return "S".$Code."_";
4778 }
4779}
4780
4781sub write_stdcxx_substitution($)
4782{
4783 my $Mangled = $_[0];
4784 if($StdcxxMangling{$Mangled}) {
4785 return $StdcxxMangling{$Mangled};
4786 }
4787 else
4788 {
4789 my @Repls = keys(%StdcxxMangling);
4790 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4791 foreach my $MangledType (@Repls)
4792 {
4793 my $Replace = $StdcxxMangling{$MangledType};
4794 #if($Mangled!~/$Replace/) {
4795 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4796 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4797 #}
4798 }
4799 }
4800 return $Mangled;
4801}
4802
4803sub write_substitution($$)
4804{
4805 my ($Mangled, $Repl) = @_;
4806 if(defined $Repl->{$Mangled}
4807 and my $MnglNum = $Repl->{$Mangled}) {
4808 $Mangled = macro_mangle($MnglNum);
4809 }
4810 else
4811 {
4812 my @Repls = keys(%{$Repl});
4813 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4814 # FIXME: how to apply replacements? by num or by pos
4815 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4816 foreach my $MangledType (@Repls)
4817 {
4818 my $Replace = macro_mangle($Repl->{$MangledType});
4819 if($Mangled!~/$Replace/) {
4820 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4821 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4822 }
4823 }
4824 }
4825 return $Mangled;
4826}
4827
4828sub delete_keywords($)
4829{
4830 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004831 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004832 return $TypeName;
4833}
4834
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004835sub uncover_typedefs($$)
4836{
4837 my ($TypeName, $LibVersion) = @_;
4838 return "" if(not $TypeName);
4839 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4840 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4841 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004842 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004843 while($TypeName_New ne $TypeName_Pre)
4844 {
4845 $TypeName_Pre = $TypeName_New;
4846 my $TypeName_Copy = $TypeName_New;
4847 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004848 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004849 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004850 if(not $Intrinsic_Keywords{$1}) {
4851 $Words{$1} = 1;
4852 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004853 }
4854 foreach my $Word (keys(%Words))
4855 {
4856 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4857 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004858 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004859 if($BaseType_Name=~/\([\*]+\)/)
4860 { # FuncPtr
4861 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4862 {
4863 my $Type_Suffix = $1;
4864 $TypeName_New = $BaseType_Name;
4865 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004866 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004867 }
4868 }
4869 }
4870 else
4871 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004872 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004873 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004874 }
4875 }
4876 }
4877 }
4878 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4879}
4880
4881sub isInternal($)
4882{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004883 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4884 {
4885 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4886 {
4887 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4888 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4889 return 1;
4890 }
4891 }
4892 }
4893 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004894}
4895
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004896sub getDataVal($$)
4897{
4898 my ($InfoId, $TypeId) = @_;
4899 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4900 {
4901 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4902 {
4903 if(defined $LibInfo{$Version}{"info_type"}{$1}
4904 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004905 {
4906 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004907 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004908 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4909 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004910 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004911 if(my $Addr = getTreeAttr_Op($1)) {
4912 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004913 }
4914 }
4915 }
4916 }
4917 else {
4918 return getInitVal($1, $TypeId);
4919 }
4920 }
4921 }
4922 return undef;
4923}
4924
4925sub getInitVal($$)
4926{
4927 my ($InfoId, $TypeId) = @_;
4928 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4929 {
4930 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4931 {
4932 if($InfoType eq "integer_cst")
4933 {
4934 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004935 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004936 { # characters
4937 $Val = chr($Val);
4938 }
4939 return $Val;
4940 }
4941 elsif($InfoType eq "string_cst") {
4942 return getNodeStrCst($InfoId);
4943 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004944 elsif($InfoType eq "var_decl")
4945 {
4946 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4947 return $Name;
4948 }
4949 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004950 }
4951 }
4952 return undef;
4953}
4954
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004955sub set_Class_And_Namespace($)
4956{
4957 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004958 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004959 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004960 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004961 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004962 my $NSInfoId = $1;
4963 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4964 {
4965 if($InfoType eq "namespace_decl") {
4966 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4967 }
4968 elsif($InfoType eq "record_type") {
4969 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4970 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004971 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004972 }
4973 }
4974 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4975 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004976 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004977 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004978 { # skip
4979 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004980 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004981 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004982
4983 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004984}
4985
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004986sub debugMangling($)
4987{
4988 my $LibVersion = $_[0];
4989 my %Mangled = ();
4990 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4991 {
4992 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4993 {
4994 if($Mngl=~/\A(_Z|\?)/) {
4995 $Mangled{$Mngl}=$InfoId;
4996 }
4997 }
4998 }
4999 translateSymbols(keys(%Mangled), $LibVersion);
5000 foreach my $Mngl (keys(%Mangled))
5001 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005002 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
5003 my $U2 = $tr_name{$Mngl};
5004 if($U1 ne $U2) {
5005 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005006 }
5007 }
5008}
5009
5010sub linkSymbol($)
5011{ # link symbols from shared libraries
5012 # with the symbols from header files
5013 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005014 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005015 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
5016 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005017 { # 1. GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
5018 # 2. GCC 4.x doesn't mangle C++ functions in the TU dump (only class methods) except extern "C" functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005019 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005020 {
5021 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
5022 return correct_incharge($InfoId, $Version, $Mangled);
5023 }
5024 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005025 if($CheckHeadersOnly
5026 or not $BinaryOnly)
5027 { # 1. --headers-only mode
5028 # 2. not mangled src-only symbols
5029 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
5030 return $Mangled;
5031 }
5032 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005033 }
5034 return "";
5035}
5036
5037sub setLanguage($$)
5038{
5039 my ($LibVersion, $Lang) = @_;
5040 if(not $UserLang) {
5041 $COMMON_LANGUAGE{$LibVersion} = $Lang;
5042 }
5043}
5044
5045sub getSymbolInfo($)
5046{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005047 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005048 if(isInternal($InfoId)) {
5049 return;
5050 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005051 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
5052 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005053 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
5054 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005055 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005056 return;
5057 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005058 setFuncAccess($InfoId);
5059 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005060 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
5061 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005062 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005063 return;
5064 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005065
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005066 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005067 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005068 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005069 if(not defined $TypeInfo{$Version}{$Return}
5070 or not $TypeInfo{$Version}{$Return}{"Name"})
5071 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005072 delete($SymbolInfo{$Version}{$InfoId});
5073 return;
5074 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005075 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005076 }
5077 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5078 {
5079 if(defined $MissedTypedef{$Version}{$Rid})
5080 {
5081 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5082 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5083 }
5084 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005085 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005086 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5087 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005088 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005089 my $Orig = getFuncOrig($InfoId);
5090 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005091 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5092 {
5093 delete($SymbolInfo{$Version}{$InfoId});
5094 return;
5095 }
5096
5097 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005098 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005099 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005100 return;
5101 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005102
5103 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005104 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005105 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5106
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005107 my @TParams = getTParams($Orig, "Func");
5108 if(not @TParams)
5109 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005110 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005111 return;
5112 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005113 foreach my $Pos (0 .. $#TParams)
5114 {
5115 my $Val = $TParams[$Pos];
5116 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5117
5118 if($Tmpl)
5119 {
5120 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5121 {
5122 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5123 }
5124 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005125 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005126
5127 if($Tmpl)
5128 {
5129 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5130 {
5131 if($Pos>$#TParams)
5132 {
5133 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5134 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5135 }
5136 }
5137 }
5138
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005139 my $PrmsInLine = join(", ", @TParams);
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005140 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5141 { # operator<< <T>, operator>> <T>
5142 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5143 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005144 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".$PrmsInLine.">";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005145 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005146 }
5147 else
5148 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005149 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005150 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005151 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5152 {
5153 if($OSgroup eq "windows")
5154 { # cut the offset
5155 $MnglName=~s/\@\d+\Z//g;
5156 }
5157 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5158
5159 # NOTE: mangling of some symbols may change depending on GCC version
5160 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5161 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5162 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005163
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005164 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005165 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005166 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005167 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005168 return;
5169 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005170 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005171 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005172 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005173 if($Skip)
5174 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005175 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005176 return;
5177 }
5178 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005179 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5180 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5181 }
5182
5183 if(set_Class_And_Namespace($InfoId))
5184 {
5185 delete($SymbolInfo{$Version}{$InfoId});
5186 return;
5187 }
5188
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005189 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5190 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005191 if(not defined $TypeInfo{$Version}{$ClassId}
5192 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5193 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005194 delete($SymbolInfo{$Version}{$InfoId});
5195 return;
5196 }
5197 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005198 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5199 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005200 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005201 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005202 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005203 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005204 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005205 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005206 }
5207 if($COMMON_LANGUAGE{$Version} eq "C++")
5208 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005209 # C++ or --headers-only mode
5210 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005211 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005212 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5213 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005214 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005215 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005216 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005217 if(my $Mangled = linkSymbol($InfoId)) {
5218 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005219 }
5220 }
5221 if($OStarget eq "windows")
5222 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005223 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005224 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005225 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005226 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005227 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005228 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005229 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005230 }
5231 }
5232 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005233 else
5234 { # not mangled in C
5235 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5236 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005237 if(not $CheckHeadersOnly
5238 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5239 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5240 {
5241 my $Incorrect = 0;
5242
5243 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5244 {
5245 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5246 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5247 { # mangled in the TU dump, but not mangled in the library
5248 $Incorrect = 1;
5249 }
5250 }
5251 else
5252 {
5253 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5254 { # all C++ functions are not mangled in the TU dump
5255 $Incorrect = 1;
5256 }
5257 }
5258 if($Incorrect)
5259 {
5260 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5261 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5262 }
5263 }
5264 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005265 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005266 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005267 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005268 return;
5269 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005270 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005271 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005272 { # identify virtual and pure virtual functions
5273 # NOTE: constructors cannot be virtual
5274 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5275 # in the TU dump, so taking it from the original symbol
5276 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5277 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5278 { # NOTE: D2 destructors are not present in a v-table
5279 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5280 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005281 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005282 if(isInline($InfoId)) {
5283 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005284 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005285 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005286 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5287 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005288 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5289 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005290 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005291 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005292 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005293 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005294 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005295 }
5296 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005297 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5298 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005299 if(not $ExtraDump)
5300 {
5301 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5302 { # non-target symbols
5303 delete($SymbolInfo{$Version}{$InfoId});
5304 return;
5305 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005306 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005307 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005308 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5309 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5310 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5311 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005312 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005313 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5314 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005315 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005316 return;
5317 }
5318 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005319 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005320 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005321 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005322 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005323 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005324 return;
5325 }
5326 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005327 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005328 }
5329 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005330 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5331 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5332 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005333 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005334 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5335 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005336 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005337 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005338 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005339 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005340 }
5341 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005342 if(getFuncLink($InfoId) eq "Static") {
5343 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005344 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005345 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5346 {
5347 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5348 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005349 if($Unmangled=~/\.\_\d/)
5350 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005351 delete($SymbolInfo{$Version}{$InfoId});
5352 return;
5353 }
5354 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005355 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005356 delete($SymbolInfo{$Version}{$InfoId}{"Type"});
5357 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5358 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005359 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005360 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5361 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005362 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005363
5364 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5365 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5366 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005367
5368 if($ExtraDump) {
5369 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5370 }
5371}
5372
5373sub guessHeader($)
5374{
5375 my $InfoId = $_[0];
5376 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5377 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5378 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5379 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5380 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5381 {
5382 if(get_filename($HPath) eq $Header)
5383 {
5384 my $HDir = get_filename(get_dirname($HPath));
5385 if($HDir ne "include"
5386 and $HDir=~/\A[a-z]+\Z/i) {
5387 return join_P($HDir, $Header);
5388 }
5389 }
5390 }
5391 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005392}
5393
5394sub isInline($)
5395{ # "body: undefined" in the tree
5396 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005397 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5398 {
5399 if($Info=~/ undefined /i) {
5400 return 0;
5401 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005402 }
5403 return 1;
5404}
5405
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005406sub hasThrow($)
5407{
5408 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5409 {
5410 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5411 return getTreeAttr_Unql($1, "unql");
5412 }
5413 }
5414 return 1;
5415}
5416
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005417sub getTypeId($)
5418{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005419 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5420 {
5421 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5422 return $1;
5423 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005424 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005425 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005426}
5427
5428sub setTypeMemb($$)
5429{
5430 my ($TypeId, $TypeAttr) = @_;
5431 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005432 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005433 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005434 if($TypeType eq "Enum")
5435 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005436 my $MInfoId = getTreeAttr_Csts($TypeId);
5437 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005438 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005439 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5440 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005441 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005442 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5443 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005444 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005445 }
5446 }
5447 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5448 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005449 my $MInfoId = getTreeAttr_Flds($TypeId);
5450 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005451 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005452 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5453 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005454 if(not $IType or $IType ne "field_decl")
5455 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005456
5457 if($IType eq "var_decl")
5458 { # static field
5459 $StaticFields = 1;
5460 }
5461
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005462 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005463 next;
5464 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005465 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005466 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005467 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005468 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005469 }
5470 if(not $StructMembName)
5471 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005472 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005473 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005474 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005475 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5476 if(isAnon($UnnamedTName))
5477 { # rename unnamed fields to unnamed0, unnamed1, ...
5478 $StructMembName = "unnamed".($UnnamedPos++);
5479 }
5480 }
5481 }
5482 if(not $StructMembName)
5483 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005484 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005485 next;
5486 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005487 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005488 if(defined $MissedTypedef{$Version}{$MembTypeId})
5489 {
5490 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5491 $MembTypeId = $AddedTid;
5492 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005493 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005494
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005495 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5496 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005497 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005498 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005499 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5500 }
5501 if($MInfo=~/spec:\s*mutable /)
5502 { # mutable fields
5503 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005504 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005505 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005506 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5507 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005508 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005509 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005510 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005511 }
5512 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005513 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005514 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5515 { # template
5516 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5517 }
5518 else {
5519 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5520 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005521 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005522
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005523 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005524 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005525 }
5526 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005527
5528 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005529}
5530
5531sub setFuncParams($)
5532{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005533 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005534 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005535 if(getFuncType($InfoId) eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005536 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005537 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5538 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005539 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005540 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005541 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5542 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005543 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005544 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5545 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005546 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005547 else
5548 { # skip
5549 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005550 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005551 # skip "this"-parameter
5552 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005553 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005554 my ($Pos, $Vtt_Pos) = (0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005555 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005556 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005557 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5558 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5559 if(not $ParamName)
5560 { # unnamed
5561 $ParamName = "p".($Pos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005562 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005563 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5564 {
5565 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5566 $ParamTypeId = $AddedTid;
5567 }
5568 }
5569 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005570 if(not $PType or $PType eq "Unknown") {
5571 return 1;
5572 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005573 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005574 if(not $PTName) {
5575 return 1;
5576 }
5577 if($PTName eq "void") {
5578 last;
5579 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005580 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005581 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005582 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005583 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005584 $ParamInfoId = getNextElem($ParamInfoId);
5585 next;
5586 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005587 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005588
5589 if(my %Base = get_BaseType($ParamTypeId, $Version))
5590 {
5591 if(defined $Base{"Template"}) {
5592 return 1;
5593 }
5594 }
5595
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005596 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005597 if(my $Algn = getAlgn($ParamInfoId)) {
5598 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5599 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005600 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"}) {
5601 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($Pos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005602 }
5603 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5604 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005605 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005606 }
5607 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005608 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005609 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005610 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005611 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005612 }
5613 return 0;
5614}
5615
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005616sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005617{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005618 my ($InfoId, $Vtt_Pos) = @_;
5619 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005620 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005621 if(getFuncType($InfoId) eq "Method") {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005622 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005623 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005624 if(not $ParamListElemId)
5625 { # foo(...)
5626 return 1;
5627 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005628 my $HaveVoid = 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005629 my $Pos = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005630 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005631 { # actual params: may differ from formal args
5632 # formal int*const
5633 # actual: int*
5634 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005635 {
5636 $Vtt_Pos=-1;
5637 $ParamListElemId = getNextElem($ParamListElemId);
5638 next;
5639 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005640 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5641 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005642 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005643 $HaveVoid = 1;
5644 last;
5645 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005646 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005647 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005648 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5649 {
5650 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5651 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5652 { # unnamed
5653 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($Pos+1);
5654 }
5655 }
5656 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5657 {
5658 if(getFuncType($InfoId) ne "Method" or $Pos>0)
5659 { # params
5660 if($OldId ne $ParamTypeId)
5661 {
5662 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5663 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5664
5665 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5666 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5667 }
5668 }
5669 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005670 }
5671 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005672 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005673 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005674 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5675 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005676 if($PurpType eq "nop_expr")
5677 { # func ( const char* arg = (const char*)(void*)0 )
5678 $PurpId = getTreeAttr_Op($PurpId);
5679 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005680 my $Val = getInitVal($PurpId, $ParamTypeId);
5681 if(defined $Val) {
5682 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5683 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005684 }
5685 }
5686 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005687 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005688 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005689 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005690}
5691
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005692sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005693{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005694 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5695 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005696 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5697 return $1;
5698 }
5699 }
5700 return "";
5701}
5702
5703sub getTreeAttr_Chain($)
5704{
5705 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5706 {
5707 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5708 return $1;
5709 }
5710 }
5711 return "";
5712}
5713
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005714sub getTreeAttr_Unql($)
5715{
5716 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5717 {
5718 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5719 return $1;
5720 }
5721 }
5722 return "";
5723}
5724
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005725sub getTreeAttr_Scpe($)
5726{
5727 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5728 {
5729 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5730 return $1;
5731 }
5732 }
5733 return "";
5734}
5735
5736sub getTreeAttr_Type($)
5737{
5738 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5739 {
5740 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5741 return $1;
5742 }
5743 }
5744 return "";
5745}
5746
5747sub getTreeAttr_Name($)
5748{
5749 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5750 {
5751 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5752 return $1;
5753 }
5754 }
5755 return "";
5756}
5757
5758sub getTreeAttr_Mngl($)
5759{
5760 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5761 {
5762 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5763 return $1;
5764 }
5765 }
5766 return "";
5767}
5768
5769sub getTreeAttr_Prms($)
5770{
5771 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5772 {
5773 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5774 return $1;
5775 }
5776 }
5777 return "";
5778}
5779
5780sub getTreeAttr_Fncs($)
5781{
5782 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5783 {
5784 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5785 return $1;
5786 }
5787 }
5788 return "";
5789}
5790
5791sub getTreeAttr_Csts($)
5792{
5793 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5794 {
5795 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5796 return $1;
5797 }
5798 }
5799 return "";
5800}
5801
5802sub getTreeAttr_Purp($)
5803{
5804 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5805 {
5806 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5807 return $1;
5808 }
5809 }
5810 return "";
5811}
5812
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005813sub getTreeAttr_Op($)
5814{
5815 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5816 {
5817 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5818 return $1;
5819 }
5820 }
5821 return "";
5822}
5823
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005824sub getTreeAttr_Valu($)
5825{
5826 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5827 {
5828 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5829 return $1;
5830 }
5831 }
5832 return "";
5833}
5834
5835sub getTreeAttr_Flds($)
5836{
5837 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5838 {
5839 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5840 return $1;
5841 }
5842 }
5843 return "";
5844}
5845
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005846sub getTreeAttr_Binf($)
5847{
5848 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5849 {
5850 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5851 return $1;
5852 }
5853 }
5854 return "";
5855}
5856
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005857sub getTreeAttr_Args($)
5858{
5859 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5860 {
5861 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005862 return $1;
5863 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005864 }
5865 return "";
5866}
5867
5868sub getTreeValue($)
5869{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005870 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5871 {
5872 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5873 return $1;
5874 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005875 }
5876 return "";
5877}
5878
5879sub getTreeAccess($)
5880{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005881 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005882 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005883 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5884 {
5885 my $Access = $1;
5886 if($Access eq "prot") {
5887 return "protected";
5888 }
5889 elsif($Access eq "priv") {
5890 return "private";
5891 }
5892 }
5893 elsif($Info=~/ protected /)
5894 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005895 return "protected";
5896 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005897 elsif($Info=~/ private /)
5898 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005899 return "private";
5900 }
5901 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005902 return "public";
5903}
5904
5905sub setFuncAccess($)
5906{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005907 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005908 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005909 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005910 }
5911 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005912 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005913 }
5914}
5915
5916sub setTypeAccess($$)
5917{
5918 my ($TypeId, $TypeAttr) = @_;
5919 my $Access = getTreeAccess($TypeId);
5920 if($Access eq "protected") {
5921 $TypeAttr->{"Protected"} = 1;
5922 }
5923 elsif($Access eq "private") {
5924 $TypeAttr->{"Private"} = 1;
5925 }
5926}
5927
5928sub setFuncKind($)
5929{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005930 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5931 {
5932 if($Info=~/pseudo tmpl/) {
5933 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5934 }
5935 elsif($Info=~/ constructor /) {
5936 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5937 }
5938 elsif($Info=~/ destructor /) {
5939 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5940 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005941 }
5942}
5943
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005944sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005945{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005946 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5947 {
5948 if($Info=~/spec[ ]*:[ ]*pure /) {
5949 return "PureVirt";
5950 }
5951 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5952 return "Virt";
5953 }
5954 elsif($Info=~/ pure\s+virtual /)
5955 { # support for old GCC versions
5956 return "PureVirt";
5957 }
5958 elsif($Info=~/ virtual /)
5959 { # support for old GCC versions
5960 return "Virt";
5961 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005962 }
5963 return "";
5964}
5965
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005966sub getFuncLink($)
5967{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005968 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5969 {
5970 if($Info=~/link[ ]*:[ ]*static /) {
5971 return "Static";
5972 }
5973 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005974 return $1;
5975 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005976 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005977 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005978}
5979
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005980sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005981{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005982 my ($Symbol, $LibVersion) = @_;
5983 return "" if(not $Symbol or not $LibVersion);
5984 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5985 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005986 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005987 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5988 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5989 }
5990 }
5991 if($NS)
5992 {
5993 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5994 return $NS;
5995 }
5996 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005997 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005998 while($NS=~s/::[^:]+\Z//)
5999 {
6000 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6001 return $NS;
6002 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006003 }
6004 }
6005 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006006
6007 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006008}
6009
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006010sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006011{
6012 my ($TypeName, $LibVersion) = @_;
6013 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006014 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006015 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006016 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6017 return $NS;
6018 }
6019 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006020 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006021 while($NS=~s/::[^:]+\Z//)
6022 {
6023 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6024 return $NS;
6025 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006026 }
6027 }
6028 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006029 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006030}
6031
6032sub getNameSpace($)
6033{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006034 my $InfoId = $_[0];
6035 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006036 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006037 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006038 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006039 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006040 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006041 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
6042 {
6043 my $NameSpace = getTreeStr($1);
6044 if($NameSpace eq "::")
6045 { # global namespace
6046 return "";
6047 }
6048 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
6049 $NameSpace = $BaseNameSpace."::".$NameSpace;
6050 }
6051 $NestedNameSpaces{$Version}{$NameSpace} = 1;
6052 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006053 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006054 else {
6055 return "";
6056 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006057 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006058 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006059 { # inside data type
6060 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6061 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006062 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006063 }
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 Ponomarenkoab282102012-03-11 11:57:02 +04006068sub getEnumMembVal($)
6069{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006070 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006071 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006072 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6073 {
6074 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6075 {
6076 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6077 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6078 return getTreeValue($1);
6079 }
6080 else
6081 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6082 return getTreeValue($1);
6083 }
6084 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006085 }
6086 }
6087 return "";
6088}
6089
6090sub getSize($)
6091{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006092 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6093 {
6094 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6095 return getTreeValue($1);
6096 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006097 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006098 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006099}
6100
6101sub getAlgn($)
6102{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006103 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6104 {
6105 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6106 return $1;
6107 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006108 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006109 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006110}
6111
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006112sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006113{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006114 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6115 {
6116 if($Info=~/ bitfield /) {
6117 return getSize($_[0]);
6118 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006119 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006120 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006121}
6122
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006123sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006124{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006125 if(my $Chan = getTreeAttr_Chan($_[0])) {
6126 return $Chan;
6127 }
6128 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6129 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006130 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006131 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006132}
6133
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006134sub registerHeader($$)
6135{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006136 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006137 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006138 return "";
6139 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006140 if(is_abs($Header) and not -f $Header)
6141 { # incorrect absolute path
6142 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006143 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006144 if(skipHeader($Header, $LibVersion))
6145 { # skip
6146 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006147 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006148 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6149 {
6150 detect_header_includes($Header_Path, $LibVersion);
6151
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006152 if(defined $Tolerance and $Tolerance=~/3/)
6153 { # 3 - skip headers that include non-Linux headers
6154 if($OSgroup ne "windows")
6155 {
6156 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6157 {
6158 if(specificHeader($Inc, "windows")) {
6159 return "";
6160 }
6161 }
6162 }
6163 }
6164
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006165 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6166 { # redirect
6167 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6168 or skipHeader($RHeader_Path, $LibVersion))
6169 { # skip
6170 return "";
6171 }
6172 $Header_Path = $RHeader_Path;
6173 }
6174 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6175 { # skip
6176 return "";
6177 }
6178
6179 if(my $HName = get_filename($Header_Path))
6180 { # register
6181 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6182 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6183 }
6184
6185 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6186 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006187 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006188 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006189 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006190 }
6191
6192 if($CheckHeadersOnly
6193 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6194 { # /usr/include/c++/4.6.1/...
6195 $STDCXX_TESTING = 1;
6196 }
6197
6198 return $Header_Path;
6199 }
6200 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006201}
6202
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006203sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006204{
6205 my ($Dir, $WithDeps, $LibVersion) = @_;
6206 $Dir=~s/[\/\\]+\Z//g;
6207 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006208 $Dir = get_abs_path($Dir);
6209 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006210 if($WithDeps)
6211 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006212 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6213 return;
6214 }
6215 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6216 $Mode = "DepsOnly";
6217 }
6218 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006219 else
6220 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006221 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6222 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6223 return;
6224 }
6225 }
6226 $Header_Dependency{$LibVersion}{$Dir} = 1;
6227 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6228 if($Mode eq "DepsOnly")
6229 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006230 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006231 $Header_Dependency{$LibVersion}{$Path} = 1;
6232 }
6233 return;
6234 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006235 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006236 {
6237 if($WithDeps)
6238 {
6239 my $SubDir = $Path;
6240 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6241 { # register all sub directories
6242 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6243 }
6244 }
6245 next if(is_not_header($Path));
6246 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006247 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006248 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006249 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6250 }
6251 }
6252 if(get_filename($Dir) eq "include")
6253 { # search for "lib/include/" directory
6254 my $LibDir = $Dir;
6255 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006256 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006257 }
6258 }
6259}
6260
6261sub parse_redirect($$$)
6262{
6263 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006264 my @Errors = ();
6265 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6266 push(@Errors, $1);
6267 }
6268 my $Redirect = "";
6269 foreach (@Errors)
6270 {
6271 s/\s{2,}/ /g;
6272 if(/(only|must\ include
6273 |update\ to\ include
6274 |replaced\ with
6275 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006276 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006277 {
6278 $Redirect = $2;
6279 last;
6280 }
6281 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6282 {
6283 $Redirect = $2;
6284 last;
6285 }
6286 elsif(/this\ header\ should\ not\ be\ used
6287 |programs\ should\ not\ directly\ include
6288 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6289 |is\ not\ supported\ API\ for\ general\ use
6290 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006291 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006292 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6293 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6294 }
6295 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006296 if($Redirect)
6297 {
6298 $Redirect=~s/\A<//g;
6299 $Redirect=~s/>\Z//g;
6300 }
6301 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006302}
6303
6304sub parse_includes($$)
6305{
6306 my ($Content, $Path) = @_;
6307 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006308 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006309 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006310 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006311 my $Method = substr($Header, 0, 1, "");
6312 substr($Header, length($Header)-1, 1, "");
6313 $Header = path_format($Header, $OSgroup);
6314 if($Method eq "\"" or is_abs($Header))
6315 {
6316 if(-e join_P(get_dirname($Path), $Header))
6317 { # relative path exists
6318 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006319 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006320 else
6321 { # include "..." that doesn't exist is equal to include <...>
6322 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006323 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006324 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006325 else {
6326 $Includes{$Header} = 1;
6327 }
6328 }
6329 if($ExtraInfo)
6330 {
6331 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6332 { # FT_FREETYPE_H
6333 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006334 }
6335 }
6336 return \%Includes;
6337}
6338
6339sub ignore_path($)
6340{
6341 my $Path = $_[0];
6342 if($Path=~/\~\Z/)
6343 {# skipping system backup files
6344 return 1;
6345 }
6346 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6347 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6348 return 1;
6349 }
6350 return 0;
6351}
6352
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006353sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006354{
6355 my ($ArrRef, $W) = @_;
6356 return if(length($W)<2);
6357 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6358}
6359
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006360sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006361{
6362 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006363
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006364 $H1=~s/\.[a-z]+\Z//ig;
6365 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006366
6367 my $Hname1 = get_filename($H1);
6368 my $Hname2 = get_filename($H2);
6369 my $HDir1 = get_dirname($H1);
6370 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006371 my $Dirname1 = get_filename($HDir1);
6372 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006373
6374 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6375 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6376
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006377 if($_[0] eq $_[1]
6378 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006379 return 0;
6380 }
6381 elsif($H1=~/\A\Q$H2\E/) {
6382 return 1;
6383 }
6384 elsif($H2=~/\A\Q$H1\E/) {
6385 return -1;
6386 }
6387 elsif($HDir1=~/\Q$Hname1\E/i
6388 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006389 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006390 return -1;
6391 }
6392 elsif($HDir2=~/\Q$Hname2\E/i
6393 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006394 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006395 return 1;
6396 }
6397 elsif($Hname1=~/\Q$Dirname1\E/i
6398 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006399 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006400 return -1;
6401 }
6402 elsif($Hname2=~/\Q$Dirname2\E/i
6403 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006404 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006405 return 1;
6406 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006407 elsif($Hname1=~/(config|lib|util)/i
6408 and $Hname2!~/(config|lib|util)/i)
6409 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006410 return -1;
6411 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006412 elsif($Hname2=~/(config|lib|util)/i
6413 and $Hname1!~/(config|lib|util)/i)
6414 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006415 return 1;
6416 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006417 else
6418 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006419 my $R1 = checkRelevance($H1);
6420 my $R2 = checkRelevance($H2);
6421 if($R1 and not $R2)
6422 { # libebook/e-book.h
6423 return -1;
6424 }
6425 elsif($R2 and not $R1)
6426 { # libebook/e-book.h
6427 return 1;
6428 }
6429 else
6430 {
6431 return (lc($H1) cmp lc($H2));
6432 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006433 }
6434}
6435
6436sub searchForHeaders($)
6437{
6438 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006439
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006440 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006441 registerGccHeaders();
6442
6443 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6444 { # c++ standard include paths
6445 registerCppHeaders();
6446 }
6447
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006448 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006449 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6450 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006451 {
6452 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006453 if($SystemRoot)
6454 {
6455 if(is_abs($Path)) {
6456 $Path = $SystemRoot.$Path;
6457 }
6458 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006459 if(not -e $Path) {
6460 exitStatus("Access_Error", "can't access \'$Path\'");
6461 }
6462 elsif(-f $Path) {
6463 exitStatus("Access_Error", "\'$Path\' - not a directory");
6464 }
6465 elsif(-d $Path)
6466 {
6467 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006468 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006469 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6470 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006471 }
6472 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006473 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006474 }
6475 }
6476 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006477 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006478 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6479 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006480
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006481 # registering directories
6482 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6483 {
6484 next if(not -e $Path);
6485 $Path = get_abs_path($Path);
6486 $Path = path_format($Path, $OSgroup);
6487 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006488 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006489 }
6490 elsif(-f $Path)
6491 {
6492 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006493 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006494 and not $LocalIncludes{$Dir})
6495 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006496 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006497 # if(my $OutDir = get_dirname($Dir))
6498 # { # registering the outer directory
6499 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6500 # and not $LocalIncludes{$OutDir}) {
6501 # registerDir($OutDir, 0, $LibVersion);
6502 # }
6503 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006504 }
6505 }
6506 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006507
6508 # clean memory
6509 %RegisteredDirs = ();
6510
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006511 # registering headers
6512 my $Position = 0;
6513 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6514 {
6515 if(is_abs($Dest) and not -e $Dest) {
6516 exitStatus("Access_Error", "can't access \'$Dest\'");
6517 }
6518 $Dest = path_format($Dest, $OSgroup);
6519 if(is_header($Dest, 1, $LibVersion))
6520 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006521 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006522 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6523 }
6524 }
6525 elsif(-d $Dest)
6526 {
6527 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006528 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006529 {
6530 next if(ignore_path($Path));
6531 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006532 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006533 push(@Registered, $HPath);
6534 }
6535 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006536 @Registered = sort {sortHeaders($a, $b)} @Registered;
6537 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006538 foreach my $Path (@Registered) {
6539 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6540 }
6541 }
6542 else {
6543 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6544 }
6545 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006546
6547 if(defined $Tolerance and $Tolerance=~/4/)
6548 { # 4 - skip headers included by others
6549 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6550 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006551 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006552 delete($Registered_Headers{$LibVersion}{$Path});
6553 }
6554 }
6555 }
6556
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006557 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6558 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006559 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006560 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006561 if(is_abs($Header) and not -f $Header) {
6562 exitStatus("Access_Error", "can't access file \'$Header\'");
6563 }
6564 $Header = path_format($Header, $OSgroup);
6565 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6566 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006567 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006568 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006569 }
6570 else {
6571 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6572 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006573 }
6574 }
6575 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6576 { # set relative paths (for duplicates)
6577 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6578 { # search for duplicates
6579 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6580 my $Prefix = get_dirname($FirstPath);
6581 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6582 { # detect a shortest distinguishing prefix
6583 my $NewPrefix = $1;
6584 my %Identity = ();
6585 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6586 {
6587 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6588 $Identity{$Path} = $1;
6589 }
6590 }
6591 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6592 { # all names are differend with current prefix
6593 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6594 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6595 }
6596 last;
6597 }
6598 $Prefix = $NewPrefix; # increase prefix
6599 }
6600 }
6601 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006602
6603 # clean memory
6604 %HeaderName_Paths = ();
6605
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006606 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6607 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006608 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006609 my ($Pos, $PairPos) = (-1, -1);
6610 my ($Path, $PairPath) = ();
6611 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6612 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6613 foreach my $Header_Path (@Paths)
6614 {
6615 if(get_filename($Header_Path) eq $PairName)
6616 {
6617 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6618 $PairPath = $Header_Path;
6619 }
6620 if(get_filename($Header_Path) eq $HeaderName)
6621 {
6622 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6623 $Path = $Header_Path;
6624 }
6625 }
6626 if($PairPos!=-1 and $Pos!=-1
6627 and int($PairPos)<int($Pos))
6628 {
6629 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6630 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6631 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6632 }
6633 }
6634 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6635 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6636 }
6637}
6638
6639sub detect_real_includes($$)
6640{
6641 my ($AbsPath, $LibVersion) = @_;
6642 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6643 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6644 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6645 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6646 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006647 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6648
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006649 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6650 return () if(not $Path);
6651 open(PREPROC, $Path);
6652 while(<PREPROC>)
6653 {
6654 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6655 {
6656 my $Include = path_format($1, $OSgroup);
6657 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6658 next;
6659 }
6660 if($Include eq $AbsPath) {
6661 next;
6662 }
6663 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6664 }
6665 }
6666 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006667 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6668}
6669
6670sub detect_header_includes($$)
6671{
6672 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006673 return if(not $LibVersion or not $Path);
6674 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6675 return;
6676 }
6677 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6678
6679 if(not -e $Path) {
6680 return;
6681 }
6682
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006683 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006684 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6685 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006686 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006687 {
6688 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006689 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006690 }
6691 if($RedirectPath ne $Path) {
6692 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6693 }
6694 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006695 else
6696 { # can't find
6697 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6698 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006699 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006700 if(my $Inc = parse_includes($Content, $Path))
6701 {
6702 foreach my $Include (keys(%{$Inc}))
6703 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006704 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006705
6706 if(defined $Tolerance and $Tolerance=~/4/)
6707 {
6708 if(my $HPath = identifyHeader($Include, $LibVersion))
6709 {
6710 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6711 }
6712 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006713 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006714 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006715}
6716
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006717sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006718{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006719 my $Path = $_[0];
6720 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006721 if($OStarget eq "symbian")
6722 {
6723 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6724 { # epoc32/include/libc/{stdio, ...}.h
6725 return 1;
6726 }
6727 }
6728 else
6729 {
6730 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6731 { # /usr/include/{stdio, ...}.h
6732 return 1;
6733 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006734 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006735 return 0;
6736}
6737
6738sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006739{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006740 my $Dir = $_[0];
6741 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006742 if($OStarget eq "symbian")
6743 {
6744 if(get_filename($OutDir) eq "libc"
6745 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6746 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6747 return 1;
6748 }
6749 }
6750 else
6751 { # linux
6752 if($OutDir eq "/usr/include"
6753 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6754 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6755 return 1;
6756 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006757 }
6758 return 0;
6759}
6760
6761sub detect_recursive_includes($$)
6762{
6763 my ($AbsPath, $LibVersion) = @_;
6764 return () if(not $AbsPath);
6765 if(isCyclical(\@RecurInclude, $AbsPath)) {
6766 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6767 }
6768 my ($AbsDir, $Name) = separate_path($AbsPath);
6769 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006770 { # system GLIBC internals
6771 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006772 }
6773 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6774 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6775 }
6776 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006777
6778 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6779 { # skip /usr/include/c++/*/ headers
6780 return () if(not $ExtraInfo);
6781 }
6782
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006783 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006784 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006785 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006786 { # check "real" (non-"model") include paths
6787 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6788 pop(@RecurInclude);
6789 return @Paths;
6790 }
6791 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6792 detect_header_includes($AbsPath, $LibVersion);
6793 }
6794 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6795 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006796 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006797 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006798 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006799 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006800 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006801 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006802 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006803 }
6804 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006805 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006806 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006807 { # search for the nearest header
6808 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006809 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006810 if(-f $Candidate) {
6811 $HPath = $Candidate;
6812 }
6813 }
6814 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006815 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006816 }
6817 next if(not $HPath);
6818 if($HPath eq $AbsPath) {
6819 next;
6820 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006821
6822 if($Debug)
6823 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006824# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6825# {
6826# print STDERR "$AbsPath -> $HPath\n";
6827# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006828 }
6829
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006830 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6831 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006832 { # only include <...>, skip include "..." prefixes
6833 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6834 }
6835 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6836 {
6837 if($IncPath eq $AbsPath) {
6838 next;
6839 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006840 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6841 if($RIncType==-1)
6842 { # include "..."
6843 $RIncType = $IncType;
6844 }
6845 elsif($RIncType==2)
6846 {
6847 if($IncType!=-1) {
6848 $RIncType = $IncType;
6849 }
6850 }
6851 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006852 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6853 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6854 }
6855 }
6856 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6857 {
6858 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6859 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6860 { # distinguish math.h from glibc and math.h from the tested library
6861 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6862 last;
6863 }
6864 }
6865 }
6866 pop(@RecurInclude);
6867 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6868}
6869
6870sub find_in_framework($$$)
6871{
6872 my ($Header, $Framework, $LibVersion) = @_;
6873 return "" if(not $Header or not $Framework or not $LibVersion);
6874 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6875 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6876 }
6877 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6878 {
6879 if(get_filename($Dependency) eq $Framework
6880 and -f get_dirname($Dependency)."/".$Header) {
6881 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6882 }
6883 }
6884 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6885}
6886
6887sub find_in_defaults($)
6888{
6889 my $Header = $_[0];
6890 return "" if(not $Header);
6891 if(defined $Cache{"find_in_defaults"}{$Header}) {
6892 return $Cache{"find_in_defaults"}{$Header};
6893 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006894 foreach my $Dir (@DefaultIncPaths,
6895 @DefaultGccPaths,
6896 @DefaultCppPaths,
6897 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006898 {
6899 next if(not $Dir);
6900 if(-f $Dir."/".$Header) {
6901 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6902 }
6903 }
6904 return ($Cache{"find_in_defaults"}{$Header}="");
6905}
6906
6907sub cmp_paths($$)
6908{
6909 my ($Path1, $Path2) = @_;
6910 my @Parts1 = split(/[\/\\]/, $Path1);
6911 my @Parts2 = split(/[\/\\]/, $Path2);
6912 foreach my $Num (0 .. $#Parts1)
6913 {
6914 my $Part1 = $Parts1[$Num];
6915 my $Part2 = $Parts2[$Num];
6916 if($GlibcDir{$Part1}
6917 and not $GlibcDir{$Part2}) {
6918 return 1;
6919 }
6920 elsif($GlibcDir{$Part2}
6921 and not $GlibcDir{$Part1}) {
6922 return -1;
6923 }
6924 elsif($Part1=~/glib/
6925 and $Part2!~/glib/) {
6926 return 1;
6927 }
6928 elsif($Part1!~/glib/
6929 and $Part2=~/glib/) {
6930 return -1;
6931 }
6932 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6933 return $CmpRes;
6934 }
6935 }
6936 return 0;
6937}
6938
6939sub checkRelevance($)
6940{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006941 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006942 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006943
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006944 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006945 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006946 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006947
6948 my $Name = lc(get_filename($Path));
6949 my $Dir = lc(get_dirname($Path));
6950
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006951 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006952
6953 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006954 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006955 my $Len = length($Token);
6956 next if($Len<=1);
6957 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6958 { # include/evolution-data-server-1.4/libebook/e-book.h
6959 return 1;
6960 }
6961 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006962 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006963 return 1;
6964 }
6965 }
6966 return 0;
6967}
6968
6969sub checkFamily(@)
6970{
6971 my @Paths = @_;
6972 return 1 if($#Paths<=0);
6973 my %Prefix = ();
6974 foreach my $Path (@Paths)
6975 {
6976 if($SystemRoot) {
6977 $Path = cut_path_prefix($Path, $SystemRoot);
6978 }
6979 if(my $Dir = get_dirname($Path))
6980 {
6981 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6982 $Prefix{$Dir} += 1;
6983 $Prefix{get_dirname($Dir)} += 1;
6984 }
6985 }
6986 foreach (sort keys(%Prefix))
6987 {
6988 if(get_depth($_)>=3
6989 and $Prefix{$_}==$#Paths+1) {
6990 return 1;
6991 }
6992 }
6993 return 0;
6994}
6995
6996sub isAcceptable($$$)
6997{
6998 my ($Header, $Candidate, $LibVersion) = @_;
6999 my $HName = get_filename($Header);
7000 if(get_dirname($Header))
7001 { # with prefix
7002 return 1;
7003 }
7004 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
7005 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
7006 return 1;
7007 }
7008 if(checkRelevance($Candidate))
7009 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
7010 return 1;
7011 }
7012 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
7013 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
7014 # /usr/include/qt4/Qt/qsslconfiguration.h
7015 return 1;
7016 }
7017 if($OStarget eq "symbian")
7018 {
7019 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
7020 return 1;
7021 }
7022 }
7023 return 0;
7024}
7025
7026sub isRelevant($$$)
7027{ # disallow to search for "abstract" headers in too deep directories
7028 my ($Header, $Candidate, $LibVersion) = @_;
7029 my $HName = get_filename($Header);
7030 if($OStarget eq "symbian")
7031 {
7032 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
7033 return 0;
7034 }
7035 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007036 if($OStarget ne "bsd")
7037 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007038 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
7039 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
7040 return 0;
7041 }
7042 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007043 if($OStarget ne "windows")
7044 {
7045 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
7046 { # skip /usr/include/wine/msvcrt
7047 return 0;
7048 }
7049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007050 if(not get_dirname($Header)
7051 and $Candidate=~/[\/\\]wx[\/\\]/)
7052 { # do NOT search in system /wx/ directory
7053 # for headers without a prefix: sstream.h
7054 return 0;
7055 }
7056 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7057 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7058 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7059 return 0;
7060 }
7061 if($Candidate=~/[\/\\]asm-/
7062 and (my $Arch = getArch($LibVersion)) ne "unknown")
7063 { # arch-specific header files
7064 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7065 {# skip ../asm-arm/ if using x86 architecture
7066 return 0;
7067 }
7068 }
7069 my @Candidates = getSystemHeaders($HName, $LibVersion);
7070 if($#Candidates==1)
7071 { # unique header
7072 return 1;
7073 }
7074 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7075 if($#SCandidates==1)
7076 { # unique name
7077 return 1;
7078 }
7079 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7080 if(get_depth($Candidate)-$SystemDepth>=5)
7081 { # abstract headers in too deep directories
7082 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7083 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7084 return 0;
7085 }
7086 }
7087 if($Header eq "parser.h"
7088 and $Candidate!~/\/libxml2\//)
7089 { # select parser.h from xml2 library
7090 return 0;
7091 }
7092 if(not get_dirname($Header)
7093 and keys(%{$SystemHeaders{$HName}})>=3)
7094 { # many headers with the same name
7095 # like thread.h included without a prefix
7096 if(not checkFamily(@Candidates)) {
7097 return 0;
7098 }
7099 }
7100 return 1;
7101}
7102
7103sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007104{ # cache function
7105 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7106 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7107 }
7108 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7109}
7110
7111sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007112{
7113 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007114 if(-f $Header) {
7115 return $Header;
7116 }
7117 if(is_abs($Header) and not -f $Header)
7118 { # incorrect absolute path
7119 return "";
7120 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007121 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007122 { # too abstract configuration headers
7123 return "";
7124 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007125 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007126 if($OSgroup ne "windows")
7127 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007128 if(defined $WinHeaders{lc($HName)}
7129 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007130 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007131 return "";
7132 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007133 }
7134 if($OSgroup ne "macos")
7135 {
7136 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007137 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007138 return "";
7139 }
7140 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007141
7142 if(defined $ObsoleteHeaders{$HName})
7143 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007144 return "";
7145 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007146 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7147 {
7148 if(defined $AlienHeaders{$HName}
7149 or defined $AlienHeaders{$Header})
7150 { # alien headers from other systems
7151 return "";
7152 }
7153 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007154
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007155 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007156 { # search in default paths
7157 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007158 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007159 }
7160 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007161 if(not keys(%SystemHeaders))
7162 { # register all headers in system include dirs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007163 detectSystemHeaders();
7164 }
7165 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7166 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7167 {
7168 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007169 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007170 }
7171 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007172 # error
7173 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007174}
7175
7176sub getSystemHeaders($$)
7177{
7178 my ($Header, $LibVersion) = @_;
7179 my @Candidates = ();
7180 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7181 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007182 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007183 next;
7184 }
7185 push(@Candidates, $Candidate);
7186 }
7187 return @Candidates;
7188}
7189
7190sub cut_path_prefix($$)
7191{
7192 my ($Path, $Prefix) = @_;
7193 return $Path if(not $Prefix);
7194 $Prefix=~s/[\/\\]+\Z//;
7195 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7196 return $Path;
7197}
7198
7199sub is_default_include_dir($)
7200{
7201 my $Dir = $_[0];
7202 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007203 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007204}
7205
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007206sub identifyHeader($$)
7207{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007208 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007209 if(not $Header) {
7210 return "";
7211 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007212 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007213 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7214 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007215 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007216 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007217}
7218
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007219sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007220{ # search for header by absolute path, relative path or name
7221 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007222 if(-f $Header)
7223 { # it's relative or absolute path
7224 return get_abs_path($Header);
7225 }
7226 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7227 and my $HeaderDir = find_in_defaults($Header))
7228 { # search for libc headers in the /usr/include
7229 # for non-libc target library before searching
7230 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007231 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007232 }
7233 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7234 { # search in the target library paths
7235 return $Path;
7236 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007237 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007238 { # search in the internal GCC include paths
7239 return $DefaultGccHeader{$Header};
7240 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007241 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007242 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007243 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007244 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007245 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007246 { # search in the default G++ include paths
7247 return $DefaultCppHeader{$Header};
7248 }
7249 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7250 { # search everywhere in the system
7251 return $AnyPath;
7252 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007253 elsif($OSgroup eq "macos")
7254 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7255 if(my $Dir = get_dirname($Header))
7256 {
7257 my $RelPath = "Headers\/".get_filename($Header);
7258 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007259 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007260 }
7261 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007262 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007263 # cannot find anything
7264 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007265}
7266
7267sub getLocation($)
7268{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007269 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7270 {
7271 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007272 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007273 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007274 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007275 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007276}
7277
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007278sub getNameByInfo($)
7279{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007280 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007281 {
7282 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7283 {
7284 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7285 {
7286 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7287 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007288 my $Str = $1;
7289 if($CppMode{$Version}
7290 and $Str=~/\Ac99_(.+)\Z/)
7291 {
7292 if($CppKeywords_A{$1}) {
7293 $Str=$1;
7294 }
7295 }
7296 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007297 }
7298 }
7299 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007300 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007301 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007302}
7303
7304sub getTreeStr($)
7305{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007306 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007307 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007308 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7309 {
7310 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007311 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007312 and $Str=~/\Ac99_(.+)\Z/)
7313 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007314 if($CppKeywords_A{$1}) {
7315 $Str=$1;
7316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007317 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007318 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007319 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007320 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007321 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007322}
7323
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007324sub getFuncShortName($)
7325{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007326 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007327 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007328 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007329 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007330 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007331 {
7332 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7333 {
7334 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7335 return "operator ".$RName;
7336 }
7337 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007338 }
7339 else
7340 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007341 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7342 {
7343 if(my $Ind = $Operator_Indication{$1}) {
7344 return "operator".$Ind;
7345 }
7346 elsif(not $UnknownOperator{$1})
7347 {
7348 printMsg("WARNING", "unknown operator $1");
7349 $UnknownOperator{$1} = 1;
7350 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007351 }
7352 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007353 }
7354 else
7355 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007356 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7357 return getTreeStr($1);
7358 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007359 }
7360 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007361 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007362}
7363
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007364sub getFuncReturn($)
7365{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007366 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7367 {
7368 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7369 {
7370 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7371 return $1;
7372 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007373 }
7374 }
7375 return "";
7376}
7377
7378sub getFuncOrig($)
7379{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007380 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7381 {
7382 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7383 return $1;
7384 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007385 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007386 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007387}
7388
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007389sub unmangleArray(@)
7390{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007391 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007392 { # MSVC mangling
7393 my $UndNameCmd = get_CmdPath("undname");
7394 if(not $UndNameCmd) {
7395 exitStatus("Not_Found", "can't find \"undname\"");
7396 }
7397 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007398 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007399 }
7400 else
7401 { # GCC mangling
7402 my $CppFiltCmd = get_CmdPath("c++filt");
7403 if(not $CppFiltCmd) {
7404 exitStatus("Not_Found", "can't find c++filt in PATH");
7405 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007406 if(not defined $CPPFILT_SUPPORT_FILE)
7407 {
7408 my $Info = `$CppFiltCmd -h 2>&1`;
7409 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7410 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007411 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007412 if($CPPFILT_SUPPORT_FILE)
7413 { # new versions of c++filt can take a file
7414 if($#_>$MAX_CPPFILT_FILE_SIZE)
7415 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7416 # this is fixed in the oncoming version of Binutils
7417 my @Half = splice(@_, 0, ($#_+1)/2);
7418 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007419 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007420 else
7421 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007422 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7423 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7424 if($?==139)
7425 { # segmentation fault
7426 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7427 }
7428 return split(/\n/, $Res);
7429 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007430 }
7431 else
7432 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007433 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7434 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007435 my @Half = splice(@_, 0, ($#_+1)/2);
7436 return (unmangleArray(@Half), unmangleArray(@_))
7437 }
7438 else
7439 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007440 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007441 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7442 if($?==139)
7443 { # segmentation fault
7444 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7445 }
7446 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007447 }
7448 }
7449 }
7450}
7451
7452sub get_SignatureNoInfo($$)
7453{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007454 my ($Symbol, $LibVersion) = @_;
7455 if($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol}) {
7456 return $Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007457 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007458 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007459 my $Signature = $tr_name{$MnglName}?$tr_name{$MnglName}:$MnglName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007460 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007461 { # C++
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04007462 # some standard typedefs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007463 $Signature=~s/\Qstd::basic_string<char, std::char_traits<char>, std::allocator<char> >\E/std::string/g;
7464 $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;
7465 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007466 if(not $CheckObjectsOnly or $OSgroup=~/linux|bsd|beos/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007467 { # ELF format marks data as OBJECT
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007468 if($GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007469 $Signature .= " [data]";
7470 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007471 elsif($Symbol!~/\A(_Z|\?)/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007472 $Signature .= " (...)";
7473 }
7474 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007475 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007476 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04007477 my $ShortName = substr($Signature, 0, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007478 $Signature=~s/\A\Q$ShortName\E/$ShortName $ChargeLevel/g;
7479 }
7480 if($SymbolVersion) {
7481 $Signature .= $VersionSpec.$SymbolVersion;
7482 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007483 return ($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007484}
7485
7486sub get_ChargeLevel($$)
7487{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007488 my ($Symbol, $LibVersion) = @_;
7489 return "" if($Symbol!~/\A(_Z|\?)/);
7490 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7491 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007492 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007493 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007494 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007495 if($Symbol=~/C1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007496 return "[in-charge]";
7497 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007498 elsif($Symbol=~/C2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007499 return "[not-in-charge]";
7500 }
7501 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007502 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007503 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007504 if($Symbol=~/D1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007505 return "[in-charge]";
7506 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007507 elsif($Symbol=~/D2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007508 return "[not-in-charge]";
7509 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007510 elsif($Symbol=~/D0E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007511 return "[in-charge-deleting]";
7512 }
7513 }
7514 }
7515 else
7516 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007517 if($Symbol=~/C1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007518 return "[in-charge]";
7519 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007520 elsif($Symbol=~/C2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007521 return "[not-in-charge]";
7522 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007523 elsif($Symbol=~/D1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007524 return "[in-charge]";
7525 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007526 elsif($Symbol=~/D2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007527 return "[not-in-charge]";
7528 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007529 elsif($Symbol=~/D0E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007530 return "[in-charge-deleting]";
7531 }
7532 }
7533 return "";
7534}
7535
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007536sub get_Signature_M($$)
7537{
7538 my ($Symbol, $LibVersion) = @_;
7539 my $Signature_M = $tr_name{$Symbol};
7540 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7541 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007542 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007543 }
7544 return $Signature_M;
7545}
7546
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007547sub get_Signature($$)
7548{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007549 my ($Symbol, $LibVersion) = @_;
7550 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7551 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007552 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007553 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
7554 if(isPrivateData($MnglName) or not $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007555 { # non-public global data
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007556 return get_SignatureNoInfo($Symbol, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007557 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007558 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007559 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7560 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007561 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007562 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7563 {
7564 $Signature .= $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::";
7565 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7566 $Signature .= "~";
7567 }
7568 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007569 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007570 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007571 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007572 }
7573 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007574 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007575 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007576 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7577 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007578 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007579 else
7580 {
7581 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007582 }
7583 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007584 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007585 {
7586 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007587 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007588 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007589 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007590 if(not $ParamTypeName) {
7591 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7592 }
7593 foreach my $Typedef (keys(%ChangedTypedef))
7594 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007595 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7596 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7597 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007598 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007599 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7600 {
7601 if($ParamName ne "this" or $Symbol!~/\A(_Z|\?)/)
7602 { # do NOT show first hidded "this"-parameter
7603 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
7604 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007605 }
7606 else {
7607 push(@ParamArray, $ParamTypeName);
7608 }
7609 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007610 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7611 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007612 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007613 }
7614 else
7615 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007616 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007617 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007618 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007619 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007620 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007621 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7622 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007623 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007624 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007625 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7626 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007627 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007628 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007629 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7630 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007631 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007632 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007633 }
7634 }
7635 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007636 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007637 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007638 }
7639 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007640 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007641 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007642 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007643}
7644
7645sub create_member_decl($$)
7646{
7647 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007648 if($TName=~/\([\*]+\)/)
7649 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007650 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7651 return $TName;
7652 }
7653 else
7654 {
7655 my @ArraySizes = ();
7656 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7657 push(@ArraySizes, $1);
7658 }
7659 return $TName." ".$Member.join("", @ArraySizes);
7660 }
7661}
7662
7663sub getFuncType($)
7664{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007665 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7666 {
7667 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7668 {
7669 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7670 {
7671 if($Type eq "method_type") {
7672 return "Method";
7673 }
7674 elsif($Type eq "function_type") {
7675 return "Function";
7676 }
7677 else {
7678 return "Other";
7679 }
7680 }
7681 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007682 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007683 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007684}
7685
7686sub getFuncTypeId($)
7687{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007688 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7689 {
7690 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7691 return $1;
7692 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007693 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007694 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007695}
7696
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007697sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007698{ # "._N" or "$_N" in older GCC versions
7699 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007700}
7701
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007702sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007703{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007704 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7705 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007706 }
7707
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007708 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007709
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007710 if($_[1] ne "S")
7711 {
7712 $N=~s/\A[ ]+//g;
7713 $N=~s/[ ]+\Z//g;
7714 $N=~s/[ ]{2,}/ /g;
7715 }
7716
7717 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007718
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007719 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007720
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007721 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7722 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007723
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007724 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007725
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007726 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007727
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007728 if($_[1] eq "S")
7729 {
7730 if(index($N, "operator")!=-1) {
7731 $N=~s/\b(operator[ ]*)> >/$1>>/;
7732 }
7733 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007734
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007735 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007736}
7737
7738sub get_HeaderDeps($$)
7739{
7740 my ($AbsPath, $LibVersion) = @_;
7741 return () if(not $AbsPath or not $LibVersion);
7742 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7743 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7744 }
7745 my %IncDir = ();
7746 detect_recursive_includes($AbsPath, $LibVersion);
7747 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7748 {
7749 next if(not $HeaderPath);
7750 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7751 my $Dir = get_dirname($HeaderPath);
7752 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7753 {
7754 my $Dep = $Dir;
7755 if($Prefix)
7756 {
7757 if($OSgroup eq "windows")
7758 { # case insensitive seach on windows
7759 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7760 next;
7761 }
7762 }
7763 elsif($OSgroup eq "macos")
7764 { # seach in frameworks
7765 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7766 {
7767 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7768 {# frameworks
7769 my ($HFramework, $HName) = ($1, $2);
7770 $Dep = $HFramework;
7771 }
7772 else
7773 {# mismatch
7774 next;
7775 }
7776 }
7777 }
7778 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7779 { # Linux, FreeBSD
7780 next;
7781 }
7782 }
7783 if(not $Dep)
7784 { # nothing to include
7785 next;
7786 }
7787 if(is_default_include_dir($Dep))
7788 { # included by the compiler
7789 next;
7790 }
7791 if(get_depth($Dep)==1)
7792 { # too short
7793 next;
7794 }
7795 if(isLibcDir($Dep))
7796 { # do NOT include /usr/include/{sys,bits}
7797 next;
7798 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007799 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007800 }
7801 }
7802 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7803 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7804}
7805
7806sub sortIncPaths($$)
7807{
7808 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007809 if(not $ArrRef or $#{$ArrRef}<0) {
7810 return $ArrRef;
7811 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007812 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7813 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007814 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007815 return $ArrRef;
7816}
7817
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007818sub sortDeps($$$)
7819{
7820 if($Header_Dependency{$_[2]}{$_[0]}
7821 and not $Header_Dependency{$_[2]}{$_[1]}) {
7822 return 1;
7823 }
7824 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7825 and $Header_Dependency{$_[2]}{$_[1]}) {
7826 return -1;
7827 }
7828 return 0;
7829}
7830
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007831sub join_P($$)
7832{
7833 my $S = "/";
7834 if($OSgroup eq "windows") {
7835 $S = "\\";
7836 }
7837 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007838}
7839
7840sub get_namespace_additions($)
7841{
7842 my $NameSpaces = $_[0];
7843 my ($Additions, $AddNameSpaceId) = ("", 1);
7844 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7845 {
7846 next if($SkipNameSpaces{$Version}{$NS});
7847 next if(not $NS or $NameSpaces->{$NS}==-1);
7848 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7849 next if($NS=~/\A__/i);
7850 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007851 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007852 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7853 my @NS_Parts = split(/::/, $NS);
7854 next if($#NS_Parts==-1);
7855 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7856 foreach my $NS_Part (@NS_Parts)
7857 {
7858 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7859 $TypeDecl_Suffix .= "}";
7860 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007861 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007862 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7863 $Additions.=" $TypeDecl\n $FuncDecl\n";
7864 $AddNameSpaceId+=1;
7865 }
7866 return $Additions;
7867}
7868
7869sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007870{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007871 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007872 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007873 if($Fmt eq "windows")
7874 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007875 $Path=~s/\//\\/g;
7876 $Path=lc($Path);
7877 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007878 else
7879 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007880 $Path=~s/\\/\//g;
7881 }
7882 return $Path;
7883}
7884
7885sub inc_opt($$)
7886{
7887 my ($Path, $Style) = @_;
7888 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007889 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007890 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007891 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007892 return "-I\"".path_format($Path, "unix")."\"";
7893 }
7894 elsif($OSgroup eq "macos"
7895 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007896 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007897 return "-F".esc(get_dirname($Path));
7898 }
7899 else {
7900 return "-I".esc($Path);
7901 }
7902 }
7903 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007904 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007905 }
7906 return "";
7907}
7908
7909sub platformSpecs($)
7910{
7911 my $LibVersion = $_[0];
7912 my $Arch = getArch($LibVersion);
7913 if($OStarget eq "symbian")
7914 { # options for GCCE compiler
7915 my %Symbian_Opts = map {$_=>1} (
7916 "-D__GCCE__",
7917 "-DUNICODE",
7918 "-fexceptions",
7919 "-D__SYMBIAN32__",
7920 "-D__MARM_INTERWORK__",
7921 "-D_UNICODE",
7922 "-D__S60_50__",
7923 "-D__S60_3X__",
7924 "-D__SERIES60_3X__",
7925 "-D__EPOC32__",
7926 "-D__MARM__",
7927 "-D__EABI__",
7928 "-D__MARM_ARMV5__",
7929 "-D__SUPPORT_CPP_EXCEPTIONS__",
7930 "-march=armv5t",
7931 "-mapcs",
7932 "-mthumb-interwork",
7933 "-DEKA2",
7934 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7935 );
7936 return join(" ", keys(%Symbian_Opts));
7937 }
7938 elsif($OSgroup eq "windows"
7939 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7940 { # add options to MinGW compiler
7941 # to simulate the MSVC compiler
7942 my %MinGW_Opts = map {$_=>1} (
7943 "-D_WIN32",
7944 "-D_STDCALL_SUPPORTED",
7945 "-D__int64=\"long long\"",
7946 "-D__int32=int",
7947 "-D__int16=short",
7948 "-D__int8=char",
7949 "-D__possibly_notnullterminated=\" \"",
7950 "-D__nullterminated=\" \"",
7951 "-D__nullnullterminated=\" \"",
7952 "-D__w64=\" \"",
7953 "-D__ptr32=\" \"",
7954 "-D__ptr64=\" \"",
7955 "-D__forceinline=inline",
7956 "-D__inline=inline",
7957 "-D__uuidof(x)=IID()",
7958 "-D__try=",
7959 "-D__except(x)=",
7960 "-D__declspec(x)=__attribute__((x))",
7961 "-D__pragma(x)=",
7962 "-D_inline=inline",
7963 "-D__forceinline=__inline",
7964 "-D__stdcall=__attribute__((__stdcall__))",
7965 "-D__cdecl=__attribute__((__cdecl__))",
7966 "-D__fastcall=__attribute__((__fastcall__))",
7967 "-D__thiscall=__attribute__((__thiscall__))",
7968 "-D_stdcall=__attribute__((__stdcall__))",
7969 "-D_cdecl=__attribute__((__cdecl__))",
7970 "-D_fastcall=__attribute__((__fastcall__))",
7971 "-D_thiscall=__attribute__((__thiscall__))",
7972 "-DSHSTDAPI_(x)=x",
7973 "-D_MSC_EXTENSIONS",
7974 "-DSECURITY_WIN32",
7975 "-D_MSC_VER=1500",
7976 "-D_USE_DECLSPECS_FOR_SAL",
7977 "-D__noop=\" \"",
7978 "-DDECLSPEC_DEPRECATED=\" \"",
7979 "-D__builtin_alignof(x)=__alignof__(x)",
7980 "-DSORTPP_PASS");
7981 if($Arch eq "x86") {
7982 $MinGW_Opts{"-D_M_IX86=300"}=1;
7983 }
7984 elsif($Arch eq "x86_64") {
7985 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7986 }
7987 elsif($Arch eq "ia64") {
7988 $MinGW_Opts{"-D_M_IA64=300"}=1;
7989 }
7990 return join(" ", keys(%MinGW_Opts));
7991 }
7992 return "";
7993}
7994
7995my %C_Structure = map {$_=>1} (
7996# FIXME: Can't separate union and struct data types before dumping,
7997# so it sometimes cause compilation errors for unknown reason
7998# when trying to declare TYPE* tmp_add_class_N
7999# This is a list of such structures + list of other C structures
8000 "sigval",
8001 "sigevent",
8002 "sigaction",
8003 "sigvec",
8004 "sigstack",
8005 "timeval",
8006 "timezone",
8007 "rusage",
8008 "rlimit",
8009 "wait",
8010 "flock",
8011 "stat",
8012 "_stat",
8013 "stat32",
8014 "_stat32",
8015 "stat64",
8016 "_stat64",
8017 "_stati64",
8018 "if_nameindex",
8019 "usb_device",
8020 "sigaltstack",
8021 "sysinfo",
8022 "timeLocale",
8023 "tcp_debug",
8024 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008025 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008026 "timespec",
8027 "random_data",
8028 "drand48_data",
8029 "_IO_marker",
8030 "_IO_FILE",
8031 "lconv",
8032 "sched_param",
8033 "tm",
8034 "itimerspec",
8035 "_pthread_cleanup_buffer",
8036 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008037 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008038 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008039 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008040 "sigcontext",
8041 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008042 # Mac
8043 "_timex",
8044 "_class_t",
8045 "_category_t",
8046 "_class_ro_t",
8047 "_protocol_t",
8048 "_message_ref_t",
8049 "_super_message_ref_t",
8050 "_ivar_t",
8051 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008052);
8053
8054sub getCompileCmd($$$)
8055{
8056 my ($Path, $Opt, $Inc) = @_;
8057 my $GccCall = $GCC_PATH;
8058 if($Opt) {
8059 $GccCall .= " ".$Opt;
8060 }
8061 $GccCall .= " -x ";
8062 if($OSgroup eq "macos") {
8063 $GccCall .= "objective-";
8064 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008065 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008066 { # compile as "C++" header
8067 # to obtain complete dump using GCC 4.0
8068 $GccCall .= "c++-header";
8069 }
8070 else
8071 { # compile as "C++" source
8072 # GCC 3.3 cannot compile headers
8073 $GccCall .= "c++";
8074 }
8075 if(my $Opts = platformSpecs($Version))
8076 {# platform-specific options
8077 $GccCall .= " ".$Opts;
8078 }
8079 # allow extra qualifications
8080 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008081 $GccCall .= " -fpermissive";
8082 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008083 if($NoStdInc)
8084 {
8085 $GccCall .= " -nostdinc";
8086 $GccCall .= " -nostdinc++";
8087 }
8088 if($CompilerOptions{$Version})
8089 { # user-defined options
8090 $GccCall .= " ".$CompilerOptions{$Version};
8091 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008092 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008093 if($Inc)
8094 { # include paths
8095 $GccCall .= " ".$Inc;
8096 }
8097 return $GccCall;
8098}
8099
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008100sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008101{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008102 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008103 my %HeaderElems = (
8104 # Types
8105 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008106 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008107 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8108 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008109 "time.h" => ["time_t"],
8110 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008111 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8112 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008113 "stdbool.h" => ["_Bool"],
8114 "rpc/xdr.h" => ["bool_t"],
8115 "in_systm.h" => ["n_long", "n_short"],
8116 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008117 "arpa/inet.h" => ["fw_src", "ip_src"],
8118 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008119 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008120 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008121 );
8122 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008123 foreach (keys(%HeaderElems))
8124 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008125 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008126 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008127 }
8128 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008129 my %Types = ();
8130 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8131 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008132 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008133 }
8134 if(keys(%Types))
8135 {
8136 my %AddHeaders = ();
8137 foreach my $Type (keys(%Types))
8138 {
8139 if(my $Header = $AutoPreamble{$Type})
8140 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008141 if(my $Path = identifyHeader($Header, $LibVersion))
8142 {
8143 if(skipHeader($Path, $LibVersion)) {
8144 next;
8145 }
8146 $Path = path_format($Path, $OSgroup);
8147 $AddHeaders{$Path}{"Type"} = $Type;
8148 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008149 }
8150 }
8151 }
8152 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008153 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008154 }
8155 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008156 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008157}
8158
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008159sub checkCTags($)
8160{
8161 my $Path = $_[0];
8162 if(not $Path) {
8163 return;
8164 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008165 my $CTags = undef;
8166
8167 if($OSgroup eq "bsd")
8168 { # use ectags on BSD
8169 $CTags = get_CmdPath("ectags");
8170 if(not $CTags) {
8171 printMsg("WARNING", "can't find \'ectags\' program");
8172 }
8173 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008174 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008175 $CTags = get_CmdPath("ctags");
8176 }
8177 if(not $CTags)
8178 {
8179 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008180 return;
8181 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008182
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008183 if($OSgroup ne "linux")
8184 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008185 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8186 if($Info!~/exuberant/i)
8187 {
8188 printMsg("WARNING", "incompatible version of \'ctags\' program");
8189 return;
8190 }
8191 }
8192
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008193 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008194 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008195 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008196 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008197 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008198 open(CTAGS, "<", $Out);
8199 while(my $Line = <CTAGS>)
8200 {
8201 chomp($Line);
8202 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008203 if(defined $Intrinsic_Keywords{$Name})
8204 { # noise
8205 next;
8206 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008207 if($Type eq "n")
8208 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008209 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008210 next;
8211 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008212 if(index($Scpe, "struct:")==0) {
8213 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008214 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008215 if(index($Scpe, "namespace:")==0)
8216 {
8217 if($Scpe=~s/\Anamespace://) {
8218 $Name = $Scpe."::".$Name;
8219 }
8220 }
8221 $TUnit_NameSpaces{$Version}{$Name} = 1;
8222 }
8223 elsif($Type eq "p")
8224 {
8225 if(not $Scpe or index($Scpe, "namespace:")==0) {
8226 $TUnit_Funcs{$Version}{$Name} = 1;
8227 }
8228 }
8229 elsif($Type eq "x")
8230 {
8231 if(not $Scpe or index($Scpe, "namespace:")==0) {
8232 $TUnit_Vars{$Version}{$Name} = 1;
8233 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008234 }
8235 }
8236 close(CTAGS);
8237}
8238
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008239sub preChange($$)
8240{
8241 my ($HeaderPath, $IncStr) = @_;
8242
8243 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8244 my $Content = undef;
8245
8246 if($OStarget eq "windows"
8247 and get_dumpmachine($GCC_PATH)=~/mingw/i
8248 and $MinGWMode{$Version}!=-1)
8249 { # modify headers to compile by MinGW
8250 if(not $Content)
8251 { # preprocessing
8252 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8253 }
8254 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8255 { # __asm { ... }
8256 $MinGWMode{$Version}=1;
8257 }
8258 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8259 { # comments after preprocessing
8260 $MinGWMode{$Version}=1;
8261 }
8262 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8263 { # 0xffui8
8264 $MinGWMode{$Version}=1;
8265 }
8266
8267 if($MinGWMode{$Version}) {
8268 printMsg("INFO", "Using MinGW compatibility mode");
8269 }
8270 }
8271
8272 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8273 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8274 { # rename C++ keywords in C code
8275 # disable this code by -cpp-compatible option
8276 if(not $Content)
8277 { # preprocessing
8278 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8279 }
8280 my $RegExp_C = join("|", keys(%CppKeywords_C));
8281 my $RegExp_F = join("|", keys(%CppKeywords_F));
8282 my $RegExp_O = join("|", keys(%CppKeywords_O));
8283
8284 my $Detected = undef;
8285
8286 while($Content=~s/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*(\,|\)|\;|\-\>|\.|\:\s*\d))/$1$2c99_$3$4/g)
8287 { # MATCH:
8288 # int foo(int new, int class, int (*new)(int));
8289 # unsigned private: 8;
8290 # DO NOT MATCH:
8291 # #pragma GCC visibility push(default)
8292 $CppMode{$Version} = 1;
8293 $Detected = "$1$2$3$4" if(not defined $Detected);
8294 }
8295 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8296 { # MATCH:
8297 # int delete(...);
8298 # int explicit(...);
8299 # DO NOT MATCH:
8300 # void operator delete(...)
8301 $CppMode{$Version} = 1;
8302 $Detected = "$1$2$3" if(not defined $Detected);
8303 }
8304 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8305 { # MATCH:
8306 # int bool;
8307 # DO NOT MATCH:
8308 # bool X;
8309 # return *this;
8310 # throw;
8311 $CppMode{$Version} = 1;
8312 $Detected = "$1$2$3" if(not defined $Detected);
8313 }
8314 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8315 { # MATCH:
8316 # int operator(...);
8317 # DO NOT MATCH:
8318 # int operator()(...);
8319 $CppMode{$Version} = 1;
8320 $Detected = "$1$2$3" if(not defined $Detected);
8321 }
8322 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8323 { # MATCH:
8324 # int foo(int operator);
8325 # int foo(int operator, int other);
8326 # DO NOT MATCH:
8327 # int operator,(...);
8328 $CppMode{$Version} = 1;
8329 $Detected = "$1$2$3" if(not defined $Detected);
8330 }
8331 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8332 { # MATCH:
8333 # int foo(gboolean *bool);
8334 # DO NOT MATCH:
8335 # void setTabEnabled(int index, bool);
8336 $CppMode{$Version} = 1;
8337 $Detected = "$1$2$3" if(not defined $Detected);
8338 }
8339 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8340 { # MATCH:
8341 # int foo(int* this);
8342 # int bar(int this);
8343 # int baz(int throw);
8344 # DO NOT MATCH:
8345 # foo(X, this);
8346 $CppMode{$Version} = 1;
8347 $Detected = "$1$2$3$4" if(not defined $Detected);
8348 }
8349 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8350 { # MATCH:
8351 # struct template {...};
8352 # extern template foo(...);
8353 $CppMode{$Version} = 1;
8354 $Detected = "$1$2" if(not defined $Detected);
8355 }
8356
8357 if($CppMode{$Version} == 1)
8358 {
8359 if($Debug)
8360 {
8361 $Detected=~s/\A\s+//g;
8362 printMsg("INFO", "Detected code: \"$Detected\"");
8363 }
8364 }
8365
8366 # remove typedef enum NAME NAME;
8367 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8368 my $N = 0;
8369 while($N<=$#FwdTypedefs-1)
8370 {
8371 my $S = $FwdTypedefs[$N];
8372 if($S eq $FwdTypedefs[$N+1])
8373 {
8374 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008375 $CppMode{$Version} = 1;
8376
8377 if($Debug) {
8378 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8379 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008380 }
8381 $N+=2;
8382 }
8383
8384 if($CppMode{$Version}==1) {
8385 printMsg("INFO", "Using C++ compatibility mode");
8386 }
8387 }
8388
8389 if($CppMode{$Version}==1
8390 or $MinGWMode{$Version}==1)
8391 {
8392 my $IPath = $TMP_DIR."/dump$Version.i";
8393 writeFile($IPath, $Content);
8394 return $IPath;
8395 }
8396
8397 return undef;
8398}
8399
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008400sub getDump()
8401{
8402 if(not $GCC_PATH) {
8403 exitStatus("Error", "internal error - GCC path is not set");
8404 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008405
8406 my @Headers = keys(%{$Registered_Headers{$Version}});
8407 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8408
8409 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8410
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008411 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008412 my $HeaderPath = $TmpHeaderPath;
8413
8414 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008415 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008416 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8417 {
8418 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008419 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008420 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008421 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008422 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8423 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008424 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008425 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008426 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008427 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8428 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8429 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008430 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008431 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008432
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008433 if($ExtraInfo)
8434 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008435 if($IncludeString) {
8436 writeFile($ExtraInfo."/include-string", $IncludeString);
8437 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008438 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8439 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008440
8441 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8442 {
8443 my $REDIR = "";
8444 foreach my $P1 (sort @Redirects) {
8445 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8446 }
8447 writeFile($ExtraInfo."/include-redirect", $REDIR);
8448 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008449 }
8450
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008451 if(not keys(%{$TargetHeaders{$Version}}))
8452 { # Target headers
8453 addTargetHeaders($Version);
8454 }
8455
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008456 # clean memory
8457 %RecursiveIncludes = ();
8458 %Header_Include_Prefix = ();
8459 %Header_Includes = ();
8460
8461 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008462 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008463 delete($Cache{"detect_header_includes"});
8464 delete($Cache{"selectSystemHeader"});
8465
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008466 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008467 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8468 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008469
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008470 if($ExtraInfo)
8471 { # extra information for other tools
8472 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8473 }
8474
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008475 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008476 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008477 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008478
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008479 if($COMMON_LANGUAGE{$Version} eq "C++") {
8480 checkCTags($Pre);
8481 }
8482
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008483 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8484 { # try to correct the preprocessor output
8485 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008486 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008487
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008488 if($COMMON_LANGUAGE{$Version} eq "C++")
8489 { # add classes and namespaces to the dump
8490 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008491 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008492 or $MinGWMode{$Version}==1) {
8493 $CHdump .= " -fpreprocessed";
8494 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008495 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008496 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008497 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008498 chdir($ORIG_DIR);
8499 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8500 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008501 my $Content = readFile($ClassDump);
8502 foreach my $ClassInfo (split(/\n\n/, $Content))
8503 {
8504 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8505 {
8506 my $CName = $1;
8507 next if($CName=~/\A(__|_objc_|_opaque_)/);
8508 $TUnit_NameSpaces{$Version}{$CName} = -1;
8509 if($CName=~/\A[\w:]+\Z/)
8510 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008511 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008512 }
8513 if($CName=~/(\w[\w:]*)::/)
8514 { # namespaces
8515 my $NS = $1;
8516 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8517 $TUnit_NameSpaces{$Version}{$NS} = 1;
8518 }
8519 }
8520 }
8521 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8522 { # read v-tables (advanced approach)
8523 my ($CName, $VTable) = ($1, $2);
8524 $ClassVTable_Content{$Version}{$CName} = $VTable;
8525 }
8526 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008527 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8528 { # add user-defined namespaces
8529 $TUnit_NameSpaces{$Version}{$NS} = 1;
8530 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008531 if($Debug)
8532 { # debug mode
8533 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008534 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008535 }
8536 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008537 }
8538
8539 # add namespaces and classes
8540 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8541 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008542 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008543 }
8544 # some GCC versions don't include class methods to the TU dump by default
8545 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008546 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008547 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8548 {
8549 next if($C_Structure{$CName});
8550 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008551 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008552 if(not $Force and $GCC_44
8553 and $OSgroup eq "linux")
8554 { # optimization for linux with GCC >= 4.4
8555 # disable this code by -force option
8556 if(index($CName, "::")!=-1)
8557 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008558 next;
8559 }
8560 }
8561 else
8562 {
8563 if($CName=~/\A(.+)::[^:]+\Z/
8564 and $TUnit_Classes{$Version}{$1})
8565 { # classes inside other classes
8566 next;
8567 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008568 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008569 if(defined $TUnit_Funcs{$Version}{$CName})
8570 { # the same name for a function and type
8571 next;
8572 }
8573 if(defined $TUnit_Vars{$Version}{$CName})
8574 { # the same name for a variable and type
8575 next;
8576 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008577 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8578 }
8579 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008580 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008581 }
8582 }
8583 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8584 # create TU dump
8585 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008586 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008587 or $MinGWMode{$Version}==1) {
8588 $TUdump .= " -fpreprocessed";
8589 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008590 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008591 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8592 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008593 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008594 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008595 if($?)
8596 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008597 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008598 { # try to recompile
8599 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008600 if($CppMode{$Version}==1
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008601 and index($Errors, "c99_")!=-1)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008602 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008603 $CppMode{$Version}=-1;
8604 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008605 resetLogging($Version);
8606 $TMP_DIR = tempdir(CLEANUP=>1);
8607 return getDump();
8608 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008609 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008610 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008611 { # add auto preamble headers and try again
8612 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008613 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008614 foreach my $Num (0 .. $#Headers)
8615 {
8616 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008617 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8618 {
8619 push_U($Include_Preamble{$Version}, $Path);
8620 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008621 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008622 }
8623 resetLogging($Version);
8624 $TMP_DIR = tempdir(CLEANUP=>1);
8625 return getDump();
8626 }
8627 elsif($Cpp0xMode{$Version}!=-1
8628 and ($Errors=~/\Q-std=c++0x\E/
8629 or $Errors=~/is not a class or namespace/))
8630 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008631 if(check_gcc($GCC_PATH, "4.6"))
8632 {
8633 $Cpp0xMode{$Version}=-1;
8634 printMsg("INFO", "Enabling c++0x mode");
8635 resetLogging($Version);
8636 $TMP_DIR = tempdir(CLEANUP=>1);
8637 $CompilerOptions{$Version} .= " -std=c++0x";
8638 return getDump();
8639 }
8640 else {
8641 printMsg("WARNING", "Probably c++0x construction detected");
8642 }
8643
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008644 }
8645 elsif($MinGWMode{$Version}==1)
8646 { # disable MinGW mode and try again
8647 $MinGWMode{$Version}=-1;
8648 resetLogging($Version);
8649 $TMP_DIR = tempdir(CLEANUP=>1);
8650 return getDump();
8651 }
8652 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008653 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008654 else {
8655 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008656 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008657 printMsg("ERROR", "some errors occurred when compiling headers");
8658 printErrorLog($Version);
8659 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008660 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008661 }
8662 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008663 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008664 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008665
8666 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8667 return $TUs[0];
8668 }
8669 else
8670 {
8671 my $Msg = "can't compile header(s)";
8672 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8673 $Msg .= "\nDid you install G++?";
8674 }
8675 exitStatus("Cannot_Compile", $Msg);
8676 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008677}
8678
8679sub cmd_file($)
8680{
8681 my $Path = $_[0];
8682 return "" if(not $Path or not -e $Path);
8683 if(my $CmdPath = get_CmdPath("file")) {
8684 return `$CmdPath -b \"$Path\"`;
8685 }
8686 return "";
8687}
8688
8689sub getIncString($$)
8690{
8691 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008692 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008693 my $String = "";
8694 foreach (@{$ArrRef}) {
8695 $String .= " ".inc_opt($_, $Style);
8696 }
8697 return $String;
8698}
8699
8700sub getIncPaths(@)
8701{
8702 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008703 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008704 if($INC_PATH_AUTODETECT{$Version})
8705 { # auto-detecting dependencies
8706 my %Includes = ();
8707 foreach my $HPath (@HeaderPaths)
8708 {
8709 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8710 {
8711 if($Skip_Include_Paths{$Version}{$Dir}) {
8712 next;
8713 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008714 if($SystemRoot)
8715 {
8716 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8717 next;
8718 }
8719 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008720 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008721 }
8722 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008723 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008724 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008725 }
8726 }
8727 else
8728 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008729 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008730 }
8731 return \@IncPaths;
8732}
8733
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008734sub push_U($@)
8735{ # push unique
8736 if(my $Array = shift @_)
8737 {
8738 if(@_)
8739 {
8740 my %Exist = map {$_=>1} @{$Array};
8741 foreach my $Elem (@_)
8742 {
8743 if(not defined $Exist{$Elem})
8744 {
8745 push(@{$Array}, $Elem);
8746 $Exist{$Elem} = 1;
8747 }
8748 }
8749 }
8750 }
8751}
8752
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008753sub callPreprocessor($$$)
8754{
8755 my ($Path, $Inc, $LibVersion) = @_;
8756 return "" if(not $Path or not -f $Path);
8757 my $IncludeString=$Inc;
8758 if(not $Inc) {
8759 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8760 }
8761 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008762 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008763 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008764 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008765}
8766
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008767sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008768{ # native "find" is much faster than File::Find (~6x)
8769 # also the File::Find doesn't support --maxdepth N option
8770 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008771 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008772 return () if(not $Path or not -e $Path);
8773 if($OSgroup eq "windows")
8774 {
8775 my $DirCmd = get_CmdPath("dir");
8776 if(not $DirCmd) {
8777 exitStatus("Not_Found", "can't find \"dir\" command");
8778 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008779 $Path = get_abs_path($Path);
8780 $Path = path_format($Path, $OSgroup);
8781 my $Cmd = $DirCmd." \"$Path\" /B /O";
8782 if($MaxDepth!=1) {
8783 $Cmd .= " /S";
8784 }
8785 if($Type eq "d") {
8786 $Cmd .= " /AD";
8787 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008788 elsif($Type eq "f") {
8789 $Cmd .= " /A-D";
8790 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008791 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008792 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008793 {
8794 if(not $UseRegex)
8795 { # FIXME: how to search file names in MS shell?
8796 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008797 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008798 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008799 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008800 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008801 }
8802 my @AbsPaths = ();
8803 foreach my $File (@Files)
8804 {
8805 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008806 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008807 }
8808 if($Type eq "f" and not -f $File)
8809 { # skip dirs
8810 next;
8811 }
8812 push(@AbsPaths, path_format($File, $OSgroup));
8813 }
8814 if($Type eq "d") {
8815 push(@AbsPaths, $Path);
8816 }
8817 return @AbsPaths;
8818 }
8819 else
8820 {
8821 my $FindCmd = get_CmdPath("find");
8822 if(not $FindCmd) {
8823 exitStatus("Not_Found", "can't find a \"find\" command");
8824 }
8825 $Path = get_abs_path($Path);
8826 if(-d $Path and -l $Path
8827 and $Path!~/\/\Z/)
8828 { # for directories that are symlinks
8829 $Path.="/";
8830 }
8831 my $Cmd = $FindCmd." \"$Path\"";
8832 if($MaxDepth) {
8833 $Cmd .= " -maxdepth $MaxDepth";
8834 }
8835 if($Type) {
8836 $Cmd .= " -type $Type";
8837 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008838 if($Name and not $UseRegex)
8839 { # wildcards
8840 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008841 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008842 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008843 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008844 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8845 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008846 my @Files = split(/\n/, $Res);
8847 if($Name and $UseRegex)
8848 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008849 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008850 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008851 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008852 }
8853}
8854
8855sub unpackDump($)
8856{
8857 my $Path = $_[0];
8858 return "" if(not $Path or not -e $Path);
8859 $Path = get_abs_path($Path);
8860 $Path = path_format($Path, $OSgroup);
8861 my ($Dir, $FileName) = separate_path($Path);
8862 my $UnpackDir = $TMP_DIR."/unpack";
8863 rmtree($UnpackDir);
8864 mkpath($UnpackDir);
8865 if($FileName=~s/\Q.zip\E\Z//g)
8866 { # *.zip
8867 my $UnzipCmd = get_CmdPath("unzip");
8868 if(not $UnzipCmd) {
8869 exitStatus("Not_Found", "can't find \"unzip\" command");
8870 }
8871 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008872 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008873 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008874 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008875 }
8876 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008877 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008878 if(not @Contents) {
8879 exitStatus("Error", "can't extract \'$Path\'");
8880 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008881 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008882 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008883 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008884 { # *.tar.gz
8885 if($OSgroup eq "windows")
8886 { # -xvzf option is not implemented in tar.exe (2003)
8887 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8888 my $TarCmd = get_CmdPath("tar");
8889 if(not $TarCmd) {
8890 exitStatus("Not_Found", "can't find \"tar\" command");
8891 }
8892 my $GzipCmd = get_CmdPath("gzip");
8893 if(not $GzipCmd) {
8894 exitStatus("Not_Found", "can't find \"gzip\" command");
8895 }
8896 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008897 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008898 if($?) {
8899 exitStatus("Error", "can't extract \'$Path\'");
8900 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008901 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008902 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008903 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008904 }
8905 chdir($ORIG_DIR);
8906 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008907 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008908 if(not @Contents) {
8909 exitStatus("Error", "can't extract \'$Path\'");
8910 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008911 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008912 }
8913 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008914 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008915 my $TarCmd = get_CmdPath("tar");
8916 if(not $TarCmd) {
8917 exitStatus("Not_Found", "can't find \"tar\" command");
8918 }
8919 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008920 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008921 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008922 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008923 }
8924 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008925 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008926 if(not @Contents) {
8927 exitStatus("Error", "can't extract \'$Path\'");
8928 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008929 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008930 }
8931 }
8932}
8933
8934sub createArchive($$)
8935{
8936 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008937 if(not $To) {
8938 $To = ".";
8939 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008940 if(not $Path or not -e $Path
8941 or not -d $To) {
8942 return "";
8943 }
8944 my ($From, $Name) = separate_path($Path);
8945 if($OSgroup eq "windows")
8946 { # *.zip
8947 my $ZipCmd = get_CmdPath("zip");
8948 if(not $ZipCmd) {
8949 exitStatus("Not_Found", "can't find \"zip\"");
8950 }
8951 my $Pkg = $To."/".$Name.".zip";
8952 unlink($Pkg);
8953 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008954 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008955 if($?)
8956 { # cannot allocate memory (or other problems with "zip")
8957 unlink($Path);
8958 exitStatus("Error", "can't pack the ABI dump: ".$!);
8959 }
8960 chdir($ORIG_DIR);
8961 unlink($Path);
8962 return $Pkg;
8963 }
8964 else
8965 { # *.tar.gz
8966 my $TarCmd = get_CmdPath("tar");
8967 if(not $TarCmd) {
8968 exitStatus("Not_Found", "can't find \"tar\"");
8969 }
8970 my $GzipCmd = get_CmdPath("gzip");
8971 if(not $GzipCmd) {
8972 exitStatus("Not_Found", "can't find \"gzip\"");
8973 }
8974 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8975 unlink($Pkg);
8976 chdir($From);
8977 system($TarCmd, "-czf", $Pkg, $Name);
8978 if($?)
8979 { # cannot allocate memory (or other problems with "tar")
8980 unlink($Path);
8981 exitStatus("Error", "can't pack the ABI dump: ".$!);
8982 }
8983 chdir($ORIG_DIR);
8984 unlink($Path);
8985 return $To."/".$Name.".tar.gz";
8986 }
8987}
8988
8989sub is_header_file($)
8990{
8991 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8992 return $_[0];
8993 }
8994 return 0;
8995}
8996
8997sub is_not_header($)
8998{
8999 if($_[0]=~/\.\w+\Z/
9000 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
9001 return 1;
9002 }
9003 return 0;
9004}
9005
9006sub is_header($$$)
9007{
9008 my ($Header, $UserDefined, $LibVersion) = @_;
9009 return 0 if(-d $Header);
9010 if(-f $Header) {
9011 $Header = get_abs_path($Header);
9012 }
9013 else
9014 {
9015 if(is_abs($Header))
9016 { # incorrect absolute path
9017 return 0;
9018 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009019 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009020 $Header = $HPath;
9021 }
9022 else
9023 { # can't find header
9024 return 0;
9025 }
9026 }
9027 if($Header=~/\.\w+\Z/)
9028 { # have an extension
9029 return is_header_file($Header);
9030 }
9031 else
9032 {
9033 if($UserDefined==2)
9034 { # specified on the command line
9035 if(cmd_file($Header)!~/HTML|XML/i) {
9036 return $Header;
9037 }
9038 }
9039 elsif($UserDefined)
9040 { # specified in the XML-descriptor
9041 # header file without an extension
9042 return $Header;
9043 }
9044 else
9045 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04009046 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009047 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009048 { # !~/HTML|XML|shared|dynamic/i
9049 return $Header;
9050 }
9051 }
9052 }
9053 return 0;
9054}
9055
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009056sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009057{
9058 my $LibVersion = $_[0];
9059 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9060 {
9061 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009062 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009063
9064 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9065 detect_recursive_includes($RegHeader, $LibVersion);
9066 }
9067
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009068 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9069 {
9070 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009071
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009072 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009073 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9074 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009075 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009076 }
9077 }
9078 }
9079}
9080
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009081sub familiarDirs($$)
9082{
9083 my ($D1, $D2) = @_;
9084 if($D1 eq $D2) {
9085 return 1;
9086 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009087
9088 my $U1 = index($D1, "/usr/");
9089 my $U2 = index($D2, "/usr/");
9090
9091 if($U1==0 and $U2!=0) {
9092 return 0;
9093 }
9094
9095 if($U2==0 and $U1!=0) {
9096 return 0;
9097 }
9098
9099 if(index($D2, $D1."/")==0) {
9100 return 1;
9101 }
9102
9103 # /usr/include/DIR
9104 # /home/user/DIR
9105
9106 my $DL = get_depth($D1);
9107
9108 my @Dirs1 = ($D1);
9109 while($DL - get_depth($D1)<=2
9110 and get_depth($D1)>=4
9111 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9112 push(@Dirs1, $D1);
9113 }
9114
9115 my @Dirs2 = ($D2);
9116 while(get_depth($D2)>=4
9117 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9118 push(@Dirs2, $D2);
9119 }
9120
9121 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009122 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009123 foreach my $P2 (@Dirs2)
9124 {
9125
9126 if($P1 eq $P2) {
9127 return 1;
9128 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009129 }
9130 }
9131 return 0;
9132}
9133
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009134sub readHeaders($)
9135{
9136 $Version = $_[0];
9137 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9138 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009139 if($Debug)
9140 { # debug mode
9141 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009142 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009143 }
9144 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009145}
9146
9147sub prepareTypes($)
9148{
9149 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009150 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009151 { # support for old ABI dumps
9152 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009153 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009154 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009155 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9156 if($TName=~/\A(\w+)::(\w+)/) {
9157 my ($P1, $P2) = ($1, $2);
9158 if($P1 eq $P2) {
9159 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009160 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009161 else {
9162 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9163 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009164 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009165 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009166 }
9167 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009168 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009169 { # support for old ABI dumps
9170 # V < 2.5: array size == "number of elements"
9171 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009172 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009173 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009174 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009175 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009176 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009177 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009178 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009179 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009180 $Size *= $Base{"Size"};
9181 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009182 }
9183 else
9184 { # array[] is a pointer
9185 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009186 }
9187 }
9188 }
9189 }
9190 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009191 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009192 { # support for old ABI dumps
9193 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009194 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009195 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009196 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009197 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009198 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009199 my %Type = get_Type($TypeId, $LibVersion);
9200 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9201 my %Type2 = get_Type($TypeId_2, $V2);
9202 if($Type{"Size"} ne $Type2{"Size"}) {
9203 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009204 }
9205 }
9206 }
9207 }
9208}
9209
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009210sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009211{
9212 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009213
9214 if(not keys(%{$SymbolInfo{$LibVersion}}))
9215 { # check if input is valid
9216 if(not $ExtendedCheck and not $CheckObjectsOnly)
9217 {
9218 if($CheckHeadersOnly) {
9219 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9220 }
9221 else {
9222 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9223 }
9224 }
9225 }
9226
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009227 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009228 if(not checkDump(1, "2.10")
9229 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009230 { # different formats
9231 $Remangle = 1;
9232 }
9233 if($CheckHeadersOnly)
9234 { # different languages
9235 if($UserLang)
9236 { # --lang=LANG for both versions
9237 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9238 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9239 {
9240 if($UserLang eq "C++")
9241 { # remangle symbols
9242 $Remangle = 1;
9243 }
9244 elsif($UserLang eq "C")
9245 { # remove mangling
9246 $Remangle = -1;
9247 }
9248 }
9249 }
9250 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009251
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009252 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009253 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009254 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009255 { # support for old ABI dumps
9256 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9257 {
9258 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9259 {
9260 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9261 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009262 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009263 if(defined $DVal and $DVal ne "")
9264 {
9265 if($TName eq "char") {
9266 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9267 }
9268 elsif($TName eq "bool") {
9269 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9270 }
9271 }
9272 }
9273 }
9274 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009275 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009276 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009277 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9278 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009279 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009280 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9281 # + support for old ABI dumps
9282 next;
9283 }
9284 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009285 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009286 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009287 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009288 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009289
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009290 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009291 if(not checkDump(1, "2.12")
9292 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009293 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009294 if($ShortName eq "operator>>")
9295 {
9296 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9297 { # corrected mangling of operator>>
9298 $SRemangle = 1;
9299 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009300 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009301 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9302 {
9303 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9304 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9305 { # corrected mangling of const global data
9306 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9307 # and incorrectly mangled by old ACC versions
9308 $SRemangle = 1;
9309 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009310 }
9311 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009312 if(not $CheckHeadersOnly)
9313 { # support for old ABI dumps
9314 if(not checkDump(1, "2.17")
9315 or not checkDump(2, "2.17"))
9316 {
9317 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9318 {
9319 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9320 {
9321 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9322 {
9323 $MnglName = $ShortName;
9324 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9325 }
9326 }
9327 }
9328 }
9329 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009330 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009331 { # support for old ABI dumps: some symbols are not mangled in old dumps
9332 # mangle both sets of symbols (old and new)
9333 # NOTE: remangling all symbols by the same mangler
9334 if($MnglName=~/\A_ZN(V|)K/)
9335 { # mangling may be incorrect on old ABI dumps
9336 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009337 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009338 }
9339 if($MnglName=~/\A_ZN(K|)V/)
9340 { # mangling may be incorrect on old ABI dumps
9341 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009342 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009343 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009344 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9345 or (not $ClassID and $CheckHeadersOnly)
9346 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9347 { # support for old ABI dumps, GCC >= 4.0
9348 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009349 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009350 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009351 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009352 $MangledNames{$LibVersion}{$MnglName} = 1;
9353 }
9354 }
9355 }
9356 elsif($Remangle==-1)
9357 { # remove mangling
9358 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009359 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009360 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009361 if(not $MnglName) {
9362 next;
9363 }
9364 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9365 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009366 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9367
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009368 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009369 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009370 { # support for old dumps
9371 # add "Volatile" attribute
9372 if($MnglName=~/_Z(K|)V/) {
9373 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9374 }
9375 }
9376 # symbol and its symlink have same signatures
9377 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009378 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009379 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009380
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009381 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9382 {
9383 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9384 if($SymVer{$LibVersion}{$Alias}) {
9385 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9386 }
9387 }
9388
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009389 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009390 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009391 }
9392 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9393 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9394 }
9395 if($ExtendedCheck)
9396 { # --ext option
9397 addExtension($LibVersion);
9398 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009399
9400 # clean memory
9401 delete($SymbolInfo{$LibVersion});
9402
9403 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009404 { # detect allocable classes with public exported constructors
9405 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009406 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009407 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009408 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009409 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009410 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9411 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009412 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009413 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009414 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009415 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009416 $AllocableClass{$LibVersion}{$ClassName} = 1;
9417 }
9418 }
9419 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009420 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009421 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009422 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009423 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009424 if($CheckHeadersOnly)
9425 {
9426 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9427 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9428 { # all symbols except non-virtual inline
9429 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9430 }
9431 }
9432 else {
9433 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009434 }
9435 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009436 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009437 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009438 }
9439 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009440 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009441 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009442 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009443 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009444 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009445 if(defined $Base{"Type"}
9446 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009447 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009448 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009449 if($Name=~/<([^<>\s]+)>/)
9450 {
9451 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9452 $ReturnedClass{$LibVersion}{$Tid} = 1;
9453 }
9454 }
9455 else {
9456 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9457 }
9458 }
9459 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009460 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009461 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009462 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009463 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009464 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009465 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009466 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009467 if($Base{"Type"}=~/Struct|Class/)
9468 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009469 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009470 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9471 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009472 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009473 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009474 }
9475 }
9476 }
9477 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009478
9479 # mapping {short name => symbols}
9480 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009481 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009482 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009483 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009484 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009485 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009486 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009487 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009488 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9489 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009490 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009491 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009492 }
9493 }
9494 }
9495 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009496
9497 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009498 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009499 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009500 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009501 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009502 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9503 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009504 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009505 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009506 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009507 $ClassNames{$LibVersion}{$TName} = 1;
9508 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009509 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009510 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9511 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009512 }
9513 }
9514 }
9515 }
9516 }
9517}
9518
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009519sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009520{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009521 my ($Tid, $LibVersion) = @_;
9522 if(not $Tid) {
9523 return $Tid;
9524 }
9525
9526 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9527 {
9528 if($TName_Tid{$LibVersion}{$Name}) {
9529 return $TName_Tid{$LibVersion}{$Name};
9530 }
9531 }
9532
9533 return $Tid;
9534}
9535
9536sub register_SymbolUsage($$$)
9537{
9538 my ($InfoId, $UsedType, $LibVersion) = @_;
9539
9540 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9541 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9542 {
9543 register_TypeUsage($RTid, $UsedType, $LibVersion);
9544 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9545 }
9546 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9547 {
9548 register_TypeUsage($FCid, $UsedType, $LibVersion);
9549 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9550
9551 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9552 { # register "this" pointer
9553 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9554 }
9555 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9556 { # register "this" pointer (const method)
9557 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9558 }
9559 }
9560 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9561 {
9562 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9563 {
9564 register_TypeUsage($PTid, $UsedType, $LibVersion);
9565 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9566 }
9567 }
9568 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9569 {
9570 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9571 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9572 register_TypeUsage($TTid, $UsedType, $LibVersion);
9573 }
9574 }
9575}
9576
9577sub register_TypeUsage($$$)
9578{
9579 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009580 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009581 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009582 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009583 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009584 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009585 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009586 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009587
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009588 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009589 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009590 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009591 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009592 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009593 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9594 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9595 }
9596 }
9597
9598 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9599 {
9600 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009601 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009602 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009603 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9604 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009605 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009606 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9607 {
9608 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9609 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009610 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009611 }
9612 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009613 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009614 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009615 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009616 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9617 {
9618 register_TypeUsage($MTid, $UsedType, $LibVersion);
9619 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009620 }
9621 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009622 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009623 or $TInfo{"Type"} eq "MethodPtr"
9624 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009625 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009626 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009627 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009628 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009629 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009630 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009631 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9632 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009633 }
9634 }
9635 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009636 if($TInfo{"Type"} eq "FieldPtr")
9637 {
9638 if(my $RTid = $TInfo{"Return"}) {
9639 register_TypeUsage($RTid, $UsedType, $LibVersion);
9640 }
9641 if(my $CTid = $TInfo{"Class"}) {
9642 register_TypeUsage($CTid, $UsedType, $LibVersion);
9643 }
9644 }
9645 if($TInfo{"Type"} eq "MethodPtr")
9646 {
9647 if(my $CTid = $TInfo{"Class"}) {
9648 register_TypeUsage($CTid, $UsedType, $LibVersion);
9649 }
9650 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009651 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009652 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009653 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009654 $UsedType->{$TypeId} = 1;
9655 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9656 {
9657 register_TypeUsage($BTid, $UsedType, $LibVersion);
9658 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9659 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009660 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009661 else
9662 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9663 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009664 }
9665 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009666}
9667
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009668sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009669{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009670 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9671
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009672 if($Level eq "Dump")
9673 {
9674 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9675 { # TODO: check if this symbol is from
9676 # base classes of other target symbols
9677 return 1;
9678 }
9679 }
9680
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009681 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9682 { # stdc++ interfaces
9683 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009684 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009685
9686 my $Target = 0;
9687 if(my $Header = $SInfo->{"Header"}) {
9688 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9689 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009690 if($ExtendedCheck)
9691 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009692 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009693 $Target = 1;
9694 }
9695 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009696 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009697 {
9698 if($Target)
9699 {
9700 if($Level eq "Dump")
9701 { # dumped
9702 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009703 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009704 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009705 return 1;
9706 }
9707 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009708 else {
9709 return 1;
9710 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009711 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009712 elsif($Level eq "Source")
9713 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009714 return 1;
9715 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009716 elsif($Level eq "Binary")
9717 { # checked
9718 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9719 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9720 return 1;
9721 }
9722 }
9723 }
9724 }
9725 else
9726 { # library is available
9727 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9728 { # exported symbols
9729 return 1;
9730 }
9731 if($Level eq "Dump")
9732 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009733 if($BinaryOnly)
9734 {
9735 if($SInfo->{"Data"})
9736 {
9737 if($Target) {
9738 return 1;
9739 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009740 }
9741 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009742 else
9743 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009744 if($Target) {
9745 return 1;
9746 }
9747 }
9748 }
9749 elsif($Level eq "Source")
9750 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009751 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
9752 or isInLineInst($Symbol, $SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009753 { # skip LOCAL symbols
9754 if($Target) {
9755 return 1;
9756 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009757 }
9758 }
9759 elsif($Level eq "Binary")
9760 { # checked
9761 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9762 {
9763 if($Target) {
9764 return 1;
9765 }
9766 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009767 }
9768 }
9769 return 0;
9770}
9771
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009772sub cleanDump($)
9773{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009774 my $LibVersion = $_[0];
9775 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9776 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009777 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9778 {
9779 delete($SymbolInfo{$LibVersion}{$InfoId});
9780 next;
9781 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009782 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009783 if(not $MnglName)
9784 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009785 delete($SymbolInfo{$LibVersion}{$InfoId});
9786 next;
9787 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009788 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009789 if(not $ShortName)
9790 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009791 delete($SymbolInfo{$LibVersion}{$InfoId});
9792 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009793 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009794 if($MnglName eq $ShortName)
9795 { # remove duplicate data
9796 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009797 }
9798 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9799 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9800 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009801 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9802 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9803 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009804 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009805 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009806 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009807 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9808 {
9809 delete($TypeInfo{$LibVersion}{$Tid});
9810 next;
9811 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009812 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009813 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009814 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009815 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9816 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9817 }
9818 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009819 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9820 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9821 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009822 }
9823}
9824
9825sub selectType($$)
9826{
9827 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009828
9829 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9830 {
9831 if(defined $TypeInfo{$LibVersion}{$Dupl})
9832 {
9833 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9834 { # duplicate
9835 return 0;
9836 }
9837 }
9838 }
9839
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009840 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9841 {
9842 if(not isBuiltIn($THeader))
9843 {
9844 if($TypeInfo{$LibVersion}{$Tid}{"Type"}=~/Class|Struct|Union|Enum|Typedef/)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009845 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009846 if(not isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"}))
9847 {
9848 if(is_target_header($THeader, $LibVersion))
9849 { # from target headers
9850 if(not selfTypedef($Tid, $LibVersion)) {
9851 return 1;
9852 }
9853 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009854 }
9855 }
9856 }
9857 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009858 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009859}
9860
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009861sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009862{ # remove unused data types from the ABI dump
9863 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009864
9865 my %UsedType = ();
9866
9867 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009868 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009869 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009870 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009871 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009872 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009873 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009874 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009875 next;
9876 }
9877
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009878 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009879 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009880 if(selectType($Tid, $LibVersion))
9881 {
9882 my %Tree = ();
9883 register_TypeUsage($Tid, \%Tree, $LibVersion);
9884
9885 my $Tmpl = 0;
9886 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9887 {
9888 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9889 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9890 {
9891 $Tmpl = 1;
9892 last;
9893 }
9894 }
9895 if(not $Tmpl)
9896 {
9897 foreach (keys(%Tree)) {
9898 $UsedType{$_} = 1;
9899 }
9900 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009901 }
9902 }
9903 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009904
9905 my %Delete = ();
9906
9907 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009908 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009909 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009910 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009911 next;
9912 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009913
9914 if($Kind eq "Extra")
9915 {
9916 my %Tree = ();
9917 register_TypeUsage($Tid, \%Tree, $LibVersion);
9918
9919 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9920 {
9921 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9922 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9923 {
9924 $Delete{$Tid} = 1;
9925 last;
9926 }
9927 }
9928 }
9929 else
9930 {
9931 # remove type
9932 delete($TypeInfo{$LibVersion}{$Tid});
9933 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009934 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009935
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009936 if($Kind eq "Extra")
9937 { # remove duplicates
9938 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9939 {
9940 if($UsedType{$Tid})
9941 { # All & Extended
9942 next;
9943 }
9944
9945 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9946
9947 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9948 delete($TypeInfo{$LibVersion}{$Tid});
9949 }
9950 }
9951 }
9952
9953 foreach my $Tid (keys(%Delete))
9954 {
9955 delete($TypeInfo{$LibVersion}{$Tid});
9956 }
9957}
9958
9959sub check_Completeness($$)
9960{
9961 my ($Info, $LibVersion) = @_;
9962
9963 # data types
9964 if(defined $Info->{"Memb"})
9965 {
9966 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9967 {
9968 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9969 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9970 }
9971 }
9972 }
9973 if(defined $Info->{"Base"})
9974 {
9975 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9976 check_TypeInfo($Bid, $LibVersion);
9977 }
9978 }
9979 if(defined $Info->{"BaseType"}) {
9980 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9981 }
9982 if(defined $Info->{"TParam"})
9983 {
9984 foreach my $Pos (keys(%{$Info->{"TParam"}}))
9985 {
9986 my $TName = $Info->{"TParam"}{$Pos}{"name"};
9987 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
9988 next;
9989 }
9990 if($TName eq "_BoolType") {
9991 next;
9992 }
9993 if($TName=~/\Asizeof\(/) {
9994 next;
9995 }
9996 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
9997 check_TypeInfo($Tid, $LibVersion);
9998 }
9999 else
10000 {
10001 if(defined $Debug) {
10002 printMsg("WARNING", "missed type $TName");
10003 }
10004 }
10005 }
10006 }
10007
10008 # symbols
10009 if(defined $Info->{"Param"})
10010 {
10011 foreach my $Pos (keys(%{$Info->{"Param"}}))
10012 {
10013 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10014 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10015 }
10016 }
10017 }
10018 if(defined $Info->{"Return"}) {
10019 check_TypeInfo($Info->{"Return"}, $LibVersion);
10020 }
10021 if(defined $Info->{"Class"}) {
10022 check_TypeInfo($Info->{"Class"}, $LibVersion);
10023 }
10024}
10025
10026sub check_TypeInfo($$)
10027{
10028 my ($Tid, $LibVersion) = @_;
10029
10030 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10031 return;
10032 }
10033 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10034
10035 if(defined $TypeInfo{$LibVersion}{$Tid})
10036 {
10037 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10038 printMsg("ERROR", "missed type name ($Tid)");
10039 }
10040 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10041 }
10042 else {
10043 printMsg("ERROR", "missed type id $Tid");
10044 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010045}
10046
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010047sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010048{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010049 my ($TypeId, $LibVersion) = @_;
10050 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010051 if($Type{"Type"} eq "Typedef")
10052 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010053 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010054 if($Base{"Type"}=~/Class|Struct/)
10055 {
10056 if($Type{"Name"} eq $Base{"Name"}) {
10057 return 1;
10058 }
10059 elsif($Type{"Name"}=~/::(\w+)\Z/)
10060 {
10061 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10062 { # QPointer<QWidget>::QPointer
10063 return 1;
10064 }
10065 }
10066 }
10067 }
10068 return 0;
10069}
10070
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010071sub addExtension($)
10072{
10073 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010074 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010075 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010076 if(selectType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010077 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010078 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10079 $TName=~s/\A(struct|union|class|enum) //;
10080 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010081
10082 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10083 "Header" => "extended.h",
10084 "ShortName" => $Symbol,
10085 "MnglName" => $Symbol,
10086 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10087 );
10088
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010089 $ExtendedSymbols{$Symbol} = 1;
10090 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10091 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010092 }
10093 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010094 $ExtendedSymbols{"external_func_0"} = 1;
10095 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10096 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010097}
10098
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010099sub findMethod($$$)
10100{
10101 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010102 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010103 {
10104 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10105 return $VirtMethodInClass;
10106 }
10107 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10108 return $VirtMethodInBaseClasses;
10109 }
10110 }
10111 return "";
10112}
10113
10114sub findMethod_Class($$$)
10115{
10116 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010117 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010118 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10119 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10120 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10121 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10122 { # search for interface with the same parameters suffix (overridden)
10123 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10124 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010125 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10126 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010127 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10128 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010129 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10130 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10131 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10132 return $Candidate;
10133 }
10134 }
10135 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010136 else
10137 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010138 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10139 return $Candidate;
10140 }
10141 }
10142 }
10143 }
10144 return "";
10145}
10146
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010147sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010148{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010149 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010150 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010151 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010152 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10153 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010154 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010155 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010156 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010157 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10158 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010159 { # pure virtual D2-destructors are marked as "virt" in the dump
10160 # virtual D2-destructors are NOT marked as "virt" in the dump
10161 # both destructors are not presented in the v-table
10162 next;
10163 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010164 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010165 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10166 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010167 }
10168}
10169
10170sub registerOverriding($)
10171{
10172 my $LibVersion = $_[0];
10173 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010174 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010175 foreach my $ClassName (@Classes)
10176 {
10177 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10178 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010179 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10180 { # pure virtuals
10181 next;
10182 }
10183 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10184 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010185 {
10186 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10187 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10188 { # both overridden virtual methods
10189 # and implemented pure virtual methods
10190 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10191 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10192 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10193 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010194 }
10195 }
10196 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10197 delete($VirtualTable{$LibVersion}{$ClassName});
10198 }
10199 }
10200}
10201
10202sub setVirtFuncPositions($)
10203{
10204 my $LibVersion = $_[0];
10205 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10206 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010207 my ($Num, $Rel) = (1, 0);
10208
10209 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010210 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010211 if($UsedDump{$LibVersion}{"DWARF"}) {
10212 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10213 }
10214 else {
10215 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10216 }
10217 foreach my $VirtFunc (@Funcs)
10218 {
10219 if($UsedDump{$LibVersion}{"DWARF"}) {
10220 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10221 }
10222 else {
10223 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10224 }
10225
10226 # set relative positions
10227 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10228 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10229 { # relative position excluding added and removed virtual functions
10230 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10231 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10232 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10233 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010234 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010235 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010236 }
10237 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010238 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010239 {
10240 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010241 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010242 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010243 }
10244 }
10245}
10246
10247sub get_sub_classes($$$)
10248{
10249 my ($ClassId, $LibVersion, $Recursive) = @_;
10250 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10251 my @Subs = ();
10252 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10253 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010254 if($Recursive)
10255 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010256 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10257 push(@Subs, $SubSubId);
10258 }
10259 }
10260 push(@Subs, $SubId);
10261 }
10262 return @Subs;
10263}
10264
10265sub get_base_classes($$$)
10266{
10267 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010268 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010269 return () if(not defined $ClassType{"Base"});
10270 my @Bases = ();
10271 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10272 keys(%{$ClassType{"Base"}}))
10273 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010274 if($Recursive)
10275 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010276 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10277 push(@Bases, $SubBaseId);
10278 }
10279 }
10280 push(@Bases, $BaseId);
10281 }
10282 return @Bases;
10283}
10284
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010285sub getVTable_Model($$)
10286{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010287 my ($ClassId, $LibVersion) = @_;
10288 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10289 my @Elements = ();
10290 foreach my $BaseId (@Bases, $ClassId)
10291 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010292 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010293 {
10294 if(defined $VirtualTable{$LibVersion}{$BName})
10295 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010296 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10297 if($UsedDump{$LibVersion}{"DWARF"}) {
10298 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10299 }
10300 else {
10301 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10302 }
10303 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010304 push(@Elements, $VFunc);
10305 }
10306 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010307 }
10308 }
10309 return @Elements;
10310}
10311
10312sub getVShift($$)
10313{
10314 my ($ClassId, $LibVersion) = @_;
10315 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10316 my $VShift = 0;
10317 foreach my $BaseId (@Bases)
10318 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010319 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010320 {
10321 if(defined $VirtualTable{$LibVersion}{$BName}) {
10322 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10323 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010324 }
10325 }
10326 return $VShift;
10327}
10328
10329sub getShift($$)
10330{
10331 my ($ClassId, $LibVersion) = @_;
10332 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10333 my $Shift = 0;
10334 foreach my $BaseId (@Bases)
10335 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010336 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010337 {
10338 if($Size!=1)
10339 { # not empty base class
10340 $Shift+=$Size;
10341 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010342 }
10343 }
10344 return $Shift;
10345}
10346
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010347sub getVTable_Size($$)
10348{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010349 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010350 my $Size = 0;
10351 # three approaches
10352 if(not $Size)
10353 { # real size
10354 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10355 $Size = keys(%VTable);
10356 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010357 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010358 if(not $Size)
10359 { # shared library symbol size
10360 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10361 $Size /= $WORD_SIZE{$LibVersion};
10362 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010363 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010364 if(not $Size)
10365 { # model size
10366 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10367 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10368 }
10369 }
10370 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010371}
10372
10373sub isCopyingClass($$)
10374{
10375 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010376 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010377}
10378
10379sub isLeafClass($$)
10380{
10381 my ($ClassId, $LibVersion) = @_;
10382 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10383}
10384
10385sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010386{ # check structured type for public fields
10387 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010388}
10389
10390sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010391{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010392 my ($TypePtr, $Skip, $Start, $End) = @_;
10393 return 0 if(not $TypePtr);
10394 if($End==-1) {
10395 $End = keys(%{$TypePtr->{"Memb"}})-1;
10396 }
10397 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}}))
10398 {
10399 if($Skip and $Skip->{$MemPos})
10400 { # skip removed/added fields
10401 next;
10402 }
10403 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10404 {
10405 if(isPublic($TypePtr, $MemPos)) {
10406 return ($MemPos+1);
10407 }
10408 }
10409 }
10410 return 0;
10411}
10412
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010413sub isReserved($)
10414{ # reserved fields == private
10415 my $MName = $_[0];
10416 if($MName=~/reserved|padding|f_spare/i) {
10417 return 1;
10418 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010419 if($MName=~/\A[_]*(spare|pad|unused)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010420 return 1;
10421 }
10422 if($MName=~/(pad\d+)/i) {
10423 return 1;
10424 }
10425 return 0;
10426}
10427
10428sub isPublic($$)
10429{
10430 my ($TypePtr, $FieldPos) = @_;
10431 return 0 if(not $TypePtr);
10432 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10433 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10434 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10435 { # by name in C language
10436 # FIXME: add other methods to detect private members
10437 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10438 if($MName=~/priv|abidata|parent_object/i)
10439 { # C-styled private data
10440 return 0;
10441 }
10442 if(lc($MName) eq "abi")
10443 { # ABI information/reserved field
10444 return 0;
10445 }
10446 if(isReserved($MName))
10447 { # reserved fields
10448 return 0;
10449 }
10450 return 1;
10451 }
10452 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10453 { # by access in C++ language
10454 return 1;
10455 }
10456 return 0;
10457}
10458
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010459sub getVTable_Real($$)
10460{
10461 my ($ClassName, $LibVersion) = @_;
10462 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10463 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010464 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010465 if(defined $Type{"VTable"}) {
10466 return %{$Type{"VTable"}};
10467 }
10468 }
10469 return ();
10470}
10471
10472sub cmpVTables($)
10473{
10474 my $ClassName = $_[0];
10475 my $Res = cmpVTables_Real($ClassName, 1);
10476 if($Res==-1) {
10477 $Res = cmpVTables_Model($ClassName);
10478 }
10479 return $Res;
10480}
10481
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010482sub cmpVTables_Model($)
10483{
10484 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010485 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010486 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010487 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010488 return 1;
10489 }
10490 }
10491 return 0;
10492}
10493
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010494sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010495{
10496 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010497 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10498 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010499 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010500 my %VTable_Old = getVTable_Real($ClassName, 1);
10501 my %VTable_New = getVTable_Real($ClassName, 2);
10502 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010503 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010504 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010505 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010506 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010507 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10508 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010509 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010510 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010511 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010512 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010513 my $Entry1 = $VTable_Old{$Offset};
10514 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010515 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010516 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010517 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010518 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010519 $Entry1 = simpleVEntry($Entry1);
10520 $Entry2 = simpleVEntry($Entry2);
10521 if($Entry1 ne $Entry2)
10522 { # register as changed
10523 if($Entry1=~/::([^:]+)\Z/)
10524 {
10525 my $M1 = $1;
10526 if($Entry2=~/::([^:]+)\Z/)
10527 {
10528 my $M2 = $1;
10529 if($M1 eq $M2)
10530 { # overridden
10531 next;
10532 }
10533 }
10534 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010535 if(differentDumps("G"))
10536 {
10537 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10538 {
10539 # GCC 4.6.1: -0x00000000000000010
10540 # GCC 4.7.0: -16
10541 next;
10542 }
10543 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010544 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010545 }
10546 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010547 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010548}
10549
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010550sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010551{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010552 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010553 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10554 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010555 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010556 { # already registered
10557 next;
10558 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010559 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010560 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010561 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010562 foreach my $Symbol (@Affected)
10563 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010564 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010565 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010566 "Target"=>$ClassName);
10567 }
10568 }
10569 }
10570}
10571
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010572sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010573{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010574 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010575 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010576 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010577 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010578 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010579 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010580 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010581 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010582 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010583 if($TName_Tid{1}{$ClassName}
10584 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010585 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010586 if(defined $CompleteSignature{1}{$Symbol}
10587 and $CompleteSignature{1}{$Symbol}{"Virt"})
10588 { # override some method in v.1
10589 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010590 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010591 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010592 }
10593 }
10594 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010595 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010596 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010597 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010598 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010599 if($TName_Tid{2}{$ClassName}
10600 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010601 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010602 if(defined $CompleteSignature{2}{$Symbol}
10603 and $CompleteSignature{2}{$Symbol}{"Virt"})
10604 { # override some method in v.2
10605 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010606 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010607 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010608 }
10609 }
10610 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010611 if($Level eq "Binary")
10612 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010613 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010614 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10615 { # check replacements, including pure virtual methods
10616 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10617 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010618 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010619 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10620 if($AddedPos==$RemovedPos)
10621 {
10622 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10623 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10624 last; # other methods will be reported as "added" or "removed"
10625 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010626 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010627 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10628 {
10629 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10630 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010631 next;
10632 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010633 my $ProblemType = "Virtual_Replacement";
10634 my @Affected = ($RemovedVFunc);
10635 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10636 { # pure methods
10637 if(not isUsedClass($ClassId, 1, $Level))
10638 { # not a parameter of some exported method
10639 next;
10640 }
10641 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010642
10643 # affected all methods (both virtual and non-virtual ones)
10644 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10645 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010646 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010647 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010648 foreach my $AffectedInt (@Affected)
10649 {
10650 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10651 { # affected exported methods only
10652 next;
10653 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010654 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10655 next;
10656 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010657 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10658 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010659 "Target"=>get_Signature($AddedVFunc, 2),
10660 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10661 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010662 }
10663 }
10664 }
10665 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010666 if(not checkDump(1, "2.0")
10667 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010668 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010669 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010670 return;
10671 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010672 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010673 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010674 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010675 next if(not $ClassId_Old);
10676 if(not isCreatable($ClassId_Old, 1))
10677 { # skip classes without public constructors (including auto-generated)
10678 # example: class has only a private exported or private inline constructor
10679 next;
10680 }
10681 if($ClassName=~/>/)
10682 { # skip affected template instances
10683 next;
10684 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010685 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010686 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010687 if(not $ClassId_New) {
10688 next;
10689 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010690 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010691 if($Class_New{"Type"}!~/Class|Struct/)
10692 { # became typedef
10693 if($Level eq "Binary") {
10694 next;
10695 }
10696 if($Level eq "Source")
10697 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010698 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010699 if($Class_New{"Type"}!~/Class|Struct/) {
10700 next;
10701 }
10702 $ClassId_New = $Class_New{"Tid"};
10703 }
10704 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010705 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10706 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 +040010707
10708 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10709 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10710
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010711 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010712 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10713 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010714 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10715 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010716 my $Shift_Old = getShift($ClassId_Old, 1);
10717 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010718 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010719 my ($Added, $Removed) = (0, 0);
10720 my @StableBases_Old = ();
10721 foreach my $BaseId (@Bases_Old)
10722 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010723 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010724 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010725 push(@StableBases_Old, $BaseId);
10726 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010727 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010728 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010729 { # removed base
10730 # excluding namespace::SomeClass to SomeClass renaming
10731 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010732 if($Level eq "Binary")
10733 { # Binary-level
10734 if($Shift_Old ne $Shift_New)
10735 { # affected fields
10736 if(havePubFields(\%Class_Old)) {
10737 $ProblemKind .= "_And_Shift";
10738 }
10739 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10740 $ProblemKind .= "_And_Size";
10741 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010742 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010743 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10744 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010745 { # affected v-table
10746 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010747 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010748 }
10749 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010750 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010751 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10752 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010753 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10754 {
10755 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10756 if($ProblemKind=~/VTable/) {
10757 $VTableChanged_M{$SubName}=1;
10758 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010759 }
10760 }
10761 foreach my $Interface (@Affected)
10762 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010763 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10764 next;
10765 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010766 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010767 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010768 "Target"=>$BaseName,
10769 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10770 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10771 "Shift"=>abs($Shift_New-$Shift_Old) );
10772 }
10773 $Removed+=1;
10774 }
10775 }
10776 my @StableBases_New = ();
10777 foreach my $BaseId (@Bases_New)
10778 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010779 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010780 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010781 push(@StableBases_New, $BaseId);
10782 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010783 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010784 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010785 { # added base
10786 # excluding namespace::SomeClass to SomeClass renaming
10787 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010788 if($Level eq "Binary")
10789 { # Binary-level
10790 if($Shift_Old ne $Shift_New)
10791 { # affected fields
10792 if(havePubFields(\%Class_Old)) {
10793 $ProblemKind .= "_And_Shift";
10794 }
10795 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10796 $ProblemKind .= "_And_Size";
10797 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010798 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010799 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10800 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010801 { # affected v-table
10802 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010803 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010804 }
10805 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010806 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010807 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10808 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010809 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10810 {
10811 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10812 if($ProblemKind=~/VTable/) {
10813 $VTableChanged_M{$SubName}=1;
10814 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010815 }
10816 }
10817 foreach my $Interface (@Affected)
10818 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010819 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10820 next;
10821 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010822 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010823 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010824 "Target"=>$BaseName,
10825 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10826 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10827 "Shift"=>abs($Shift_New-$Shift_Old) );
10828 }
10829 $Added+=1;
10830 }
10831 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010832 if($Level eq "Binary")
10833 { # Binary-level
10834 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010835 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10836 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010837 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010838 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010839 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010840 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010841 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010842 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10843 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010844 if($NewPos!=$OldPos)
10845 { # changed position of the base class
10846 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010847 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010848 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10849 next;
10850 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010851 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10852 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010853 "Target"=>$BaseName,
10854 "Old_Value"=>$OldPos-1,
10855 "New_Value"=>$NewPos-1 );
10856 }
10857 }
10858 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10859 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10860 { # became non-virtual base
10861 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10862 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010863 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10864 next;
10865 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010866 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10867 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010868 "Target"=>$BaseName );
10869 }
10870 }
10871 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10872 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10873 { # became virtual base
10874 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10875 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010876 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10877 next;
10878 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010879 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10880 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010881 "Target"=>$BaseName );
10882 }
10883 }
10884 }
10885 }
10886 # detect size changes in base classes
10887 if($Shift_Old!=$Shift_New)
10888 { # size of allocable class
10889 foreach my $BaseId (@StableBases_Old)
10890 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010891 my %BaseType = get_Type($BaseId, 1);
10892 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010893 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010894 if($Size_Old ne $Size_New
10895 and $Size_Old and $Size_New)
10896 {
10897 my $ProblemType = "";
10898 if(isCopyingClass($BaseId, 1)) {
10899 $ProblemType = "Size_Of_Copying_Class";
10900 }
10901 elsif($AllocableClass{1}{$BaseType{"Name"}})
10902 {
10903 if($Size_New>$Size_Old)
10904 { # increased size
10905 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010906 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010907 else
10908 { # decreased size
10909 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10910 if(not havePubFields(\%Class_Old))
10911 { # affected class has no public members
10912 next;
10913 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010914 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010915 }
10916 next if(not $ProblemType);
10917 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10918 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010919 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10920 next;
10921 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010922 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10923 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010924 "Target"=>$BaseType{"Name"},
10925 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10926 "New_Size"=>$Size_New*$BYTE_SIZE );
10927 }
10928 }
10929 }
10930 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010931 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010932 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010933 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010934 { # compare virtual tables size in base classes
10935 my $VShift_Old = getVShift($ClassId_Old, 1);
10936 my $VShift_New = getVShift($ClassId_New, 2);
10937 if($VShift_Old ne $VShift_New)
10938 { # changes in the base class or changes in the list of base classes
10939 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10940 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10941 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010942 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010943 foreach my $BaseId (@AllBases_Old)
10944 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010945 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010946 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010947 { # lost base
10948 next;
10949 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010950 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10951 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010952 if($VSize_Old!=$VSize_New)
10953 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010954 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010955 { # TODO: affected non-virtual methods?
10956 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010957 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10958 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010959 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010960 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010961 { # skip interfaces that have not changed the absolute virtual position
10962 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010963 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010964 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10965 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010966 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010967 $VTableChanged_M{$BaseType{"Name"}} = 1;
10968 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010969 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10970 { # the reason of the layout change: added virtual functions
10971 next if($VirtualReplacement{$VirtFunc});
10972 my $ProblemType = "Added_Virtual_Method";
10973 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10974 $ProblemType = "Added_Pure_Virtual_Method";
10975 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010976 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010977 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010978 "Target"=>get_Signature($VirtFunc, 2) );
10979 }
10980 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
10981 { # the reason of the layout change: removed virtual functions
10982 next if($VirtualReplacement{$VirtFunc});
10983 my $ProblemType = "Removed_Virtual_Method";
10984 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
10985 $ProblemType = "Removed_Pure_Virtual_Method";
10986 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010987 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010988 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010989 "Target"=>get_Signature($VirtFunc, 1) );
10990 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010991 }
10992 }
10993 }
10994 }
10995 }
10996 }
10997 }
10998}
10999
11000sub isCreatable($$)
11001{
11002 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011003 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011004 or isCopyingClass($ClassId, $LibVersion)) {
11005 return 1;
11006 }
11007 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11008 { # Fix for incomplete data: if this class has
11009 # a base class then it should also has a constructor
11010 return 1;
11011 }
11012 if($ReturnedClass{$LibVersion}{$ClassId})
11013 { # returned by some method of this class
11014 # or any other class
11015 return 1;
11016 }
11017 return 0;
11018}
11019
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011020sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011021{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011022 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011023 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11024 { # parameter of some exported method
11025 return 1;
11026 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011027 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11028 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011029 { # method from target class
11030 return 1;
11031 }
11032 return 0;
11033}
11034
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011035sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011036{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011037 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011038 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011039 # - virtual
11040 # - pure-virtual
11041 # - non-virtual
11042 if($CompleteSignature{1}{$Interface}{"Data"})
11043 { # global data is not affected
11044 return;
11045 }
11046 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011047 if(not $Class_Id) {
11048 return;
11049 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011050 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011051 if(cmpVTables_Real($CName, 1)==0)
11052 { # no changes
11053 return;
11054 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011055 $CheckedTypes{$Level}{$CName} = 1;
11056 if($Level eq "Binary")
11057 { # Binary-level
11058 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11059 and not isUsedClass($Class_Id, 1, $Level))
11060 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011061 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011062 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011063 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011064 }
11065 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11066 {
11067 if(defined $VirtualTable{2}{$CName}{$Func}
11068 and defined $CompleteSignature{2}{$Func})
11069 {
11070 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11071 and $CompleteSignature{2}{$Func}{"PureVirt"})
11072 { # became pure virtual
11073 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11074 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011075 "Target"=>get_Signature_M($Func, 1) );
11076 $VTableChanged_M{$CName} = 1;
11077 }
11078 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11079 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11080 { # became non-pure virtual
11081 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11082 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011083 "Target"=>get_Signature_M($Func, 1) );
11084 $VTableChanged_M{$CName} = 1;
11085 }
11086 }
11087 }
11088 if($Level eq "Binary")
11089 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011090 # check virtual table structure
11091 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11092 {
11093 next if($Interface eq $AddedVFunc);
11094 next if($VirtualReplacement{$AddedVFunc});
11095 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11096 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11097 { # pure virtual methods affect all others (virtual and non-virtual)
11098 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011099 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011100 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011101 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011102 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011103 elsif(not defined $VirtualTable{1}{$CName}
11104 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011105 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011106 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011107 { # became polymorphous class, added v-table pointer
11108 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011109 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011110 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011111 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011112 }
11113 else
11114 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011115 my $VSize_Old = getVTable_Size($CName, 1);
11116 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011117 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011118 if(isCopyingClass($Class_Id, 1))
11119 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11120 my $ProblemType = "Added_Virtual_Method";
11121 if(isLeafClass($Class_Id, 1)) {
11122 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11123 }
11124 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11125 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011126 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011127 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011128 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011129 else
11130 {
11131 my $ProblemType = "Added_Virtual_Method";
11132 if(isLeafClass($Class_Id, 1)) {
11133 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11134 }
11135 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11136 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011137 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011138 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011139 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011140 }
11141 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011142 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11143 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011144 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011145 if(defined $VirtualTable{1}{$CName}
11146 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011147 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011148 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11149 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011150
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011151 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011152 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011153 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11154 foreach my $ASymbol (@Affected)
11155 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011156 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11157 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011158 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011159 next;
11160 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011161 }
11162 $CheckedSymbols{$Level}{$ASymbol} = 1;
11163 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11164 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011165 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011166 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011167 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011168 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011169 }
11170 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011171 else {
11172 # safe
11173 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011174 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011175 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11176 {
11177 next if($VirtualReplacement{$RemovedVFunc});
11178 if($RemovedVFunc eq $Interface
11179 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11180 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011181 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011182 next;
11183 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011184 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011185 { # became non-polymorphous class, removed v-table pointer
11186 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11187 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011188 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011189 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011190 }
11191 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11192 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11193 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011194 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011195 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011196 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11197 next;
11198 }
11199 my $VPos_New = -1;
11200 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011201 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011202 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11203 }
11204 else
11205 {
11206 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011207 next;
11208 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011209 }
11210 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11211 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11212 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11213 {
11214 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11215 foreach my $ASymbol (@Affected)
11216 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011217 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11218 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011219 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011220 next;
11221 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011222 }
11223 my $ProblemType = "Removed_Virtual_Method";
11224 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11225 $ProblemType = "Removed_Pure_Virtual_Method";
11226 }
11227 $CheckedSymbols{$Level}{$ASymbol} = 1;
11228 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11229 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011230 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011231 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011232 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011233 }
11234 }
11235 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011236 }
11237 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011238 else
11239 { # Source-level
11240 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011241 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011242 next if($Interface eq $AddedVFunc);
11243 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011244 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011245 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11246 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011247 "Target"=>get_Signature($AddedVFunc, 2) );
11248 }
11249 }
11250 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11251 {
11252 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11253 {
11254 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11255 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011256 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011257 }
11258 }
11259 }
11260}
11261
11262sub find_MemberPair_Pos_byName($$)
11263{
11264 my ($Member_Name, $Pair_Type) = @_;
11265 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11266 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11267 {
11268 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11269 {
11270 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11271 $Name=~s/\A[_]+|[_]+\Z//g;
11272 if($Name eq $Member_Name) {
11273 return $MemberPair_Pos;
11274 }
11275 }
11276 }
11277 return "lost";
11278}
11279
11280sub find_MemberPair_Pos_byVal($$)
11281{
11282 my ($Member_Value, $Pair_Type) = @_;
11283 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11284 {
11285 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11286 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11287 return $MemberPair_Pos;
11288 }
11289 }
11290 return "lost";
11291}
11292
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011293my %Severity_Val=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011294 "High"=>3,
11295 "Medium"=>2,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011296 "Low"=>1,
11297 "Safe"=>-1
11298);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011299
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011300sub maxSeverity($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011301{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011302 my ($S1, $S2) = @_;
11303 if(cmpSeverities($S1, $S2)) {
11304 return $S1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011305 }
11306 else {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011307 return $S2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011308 }
11309}
11310
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011311sub cmpSeverities($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011312{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011313 my ($S1, $S2) = @_;
11314 if(not $S1) {
11315 return 0;
11316 }
11317 elsif(not $S2) {
11318 return 1;
11319 }
11320 return ($Severity_Val{$S1}>$Severity_Val{$S2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011321}
11322
11323sub getProblemSeverity($$)
11324{
11325 my ($Level, $Kind) = @_;
11326 return $CompatRules{$Level}{$Kind}{"Severity"};
11327}
11328
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011329sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011330{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011331 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011332 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011333 if( $_->{"T1"} eq $_[0]
11334 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011335 {
11336 return 1;
11337 }
11338 }
11339 return 0;
11340}
11341
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011342sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011343{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011344 my %IDs = (
11345 "T1" => $_[0],
11346 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011347 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011348 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011349}
11350
11351sub isRenamed($$$$$)
11352{
11353 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11354 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11355 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011356 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011357 if(not defined $Type2->{"Memb"}{$MemPos}) {
11358 return "";
11359 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011360 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011361 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011362
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011363 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11364 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011365 if($MemberPair_Pos_Rev eq "lost")
11366 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011367 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11368 { # base type match
11369 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011370 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011371 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11372 { # exact type match
11373 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011374 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011375 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11376 { # size match
11377 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011378 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011379 if(isReserved($Pair_Name))
11380 { # reserved fields
11381 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011382 }
11383 }
11384 return "";
11385}
11386
11387sub isLastElem($$)
11388{
11389 my ($Pos, $TypeRef) = @_;
11390 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11391 if($Name=~/last|count|max|total/i)
11392 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11393 return 1;
11394 }
11395 elsif($Name=~/END|NLIMITS\Z/)
11396 { # __RLIMIT_NLIMITS
11397 return 1;
11398 }
11399 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11400 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11401 { # NImageFormats, NColorRoles
11402 return 1;
11403 }
11404 return 0;
11405}
11406
11407sub nonComparable($$)
11408{
11409 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011410
11411 my $N1 = $T1->{"Name"};
11412 my $N2 = $T2->{"Name"};
11413
11414 $N1=~s/\A(struct|union|enum) //;
11415 $N2=~s/\A(struct|union|enum) //;
11416
11417 if($N1 ne $N2
11418 and not isAnon($N1)
11419 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011420 { # different names
11421 if($T1->{"Type"} ne "Pointer"
11422 or $T2->{"Type"} ne "Pointer")
11423 { # compare base types
11424 return 1;
11425 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011426 if($N1!~/\Avoid\s*\*/
11427 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011428 {
11429 return 1;
11430 }
11431 }
11432 elsif($T1->{"Type"} ne $T2->{"Type"})
11433 { # different types
11434 if($T1->{"Type"} eq "Class"
11435 and $T2->{"Type"} eq "Struct")
11436 { # "class" to "struct"
11437 return 0;
11438 }
11439 elsif($T2->{"Type"} eq "Class"
11440 and $T1->{"Type"} eq "Struct")
11441 { # "struct" to "class"
11442 return 0;
11443 }
11444 else
11445 { # "class" to "enum"
11446 # "union" to "class"
11447 # ...
11448 return 1;
11449 }
11450 }
11451 return 0;
11452}
11453
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011454sub isOpaque($)
11455{
11456 my $T = $_[0];
11457 if(not defined $T->{"Memb"})
11458 {
11459 return 1;
11460 }
11461 return 0;
11462}
11463
11464sub removeVPtr($)
11465{ # support for old ABI dumps
11466 my $TPtr = $_[0];
11467 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11468 if($#Pos>=1)
11469 {
11470 foreach my $Pos (0 .. $#Pos-1)
11471 {
11472 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11473 }
11474 delete($TPtr->{"Memb"}{$#Pos});
11475 }
11476}
11477
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011478sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011479{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011480 my ($Type1_Id, $Type2_Id, $Level) = @_;
11481 return () if(not $Type1_Id or not $Type2_Id);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011482 my (%Sub_SubProblems, %SubProblems) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011483 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011484 { # already merged
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011485 return %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011486 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011487 my %Type1 = get_Type($Type1_Id, 1);
11488 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011489 if(not $Type1{"Name"} or not $Type2{"Name"}) {
11490 return ();
11491 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011492
11493 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011494 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11495 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011496 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11497
11498 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11499 {
11500 if($Type1_Pure{"Type"}=~/Struct|Union/
11501 and $Type2_Pure{"Type"}=~/Struct|Union/)
11502 {
11503 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11504 {
11505 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11506 "Target"=>$Type1_Pure{"Name"},
11507 "Type_Name"=>$Type1_Pure{"Name"} );
11508
11509 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
11510 return %SubProblems;
11511 }
11512 }
11513 }
11514
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011515 if(not $Type1_Pure{"Size"}
11516 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011517 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011518 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11519 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11520 { # NOTE: template instances have no size
11521 return ();
11522 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011523 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011524 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011525 { # skip recursive declarations
11526 return ();
11527 }
11528 return () if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11529 return () if($SkipTypes{1}{$Type1_Pure{"Name"}});
11530 return () if($SkipTypes{1}{$Type1{"Name"}});
11531
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011532 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11533 { # support for old ABI dumps
11534 # _vptr field added in 3.0
11535 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11536 {
11537 if(defined $Type2_Pure{"Memb"}
11538 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11539 {
11540 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11541 delete($Type2_Pure{"Memb"}{0});
11542 }
11543 else {
11544 removeVPtr(\%Type2_Pure);
11545 }
11546 }
11547 }
11548 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11549 {
11550 if(defined $Type1_Pure{"Memb"}
11551 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11552 {
11553 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11554 delete($Type1_Pure{"Memb"}{0});
11555 }
11556 else {
11557 removeVPtr(\%Type1_Pure);
11558 }
11559 }
11560 }
11561 }
11562
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011563 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11564 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011565
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011566 if(not $UseOldDumps and %Typedef_1 and %Typedef_2
11567 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11568 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011569 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011570 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11571 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011572 if($Base_1{"Name"} ne $Base_2{"Name"})
11573 {
11574 if(differentDumps("G")
11575 or differentDumps("V"))
11576 { # different GCC versions or different dumps
11577 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11578 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11579 # std::__va_list and __va_list
11580 $Base_1{"Name"}=~s/\A(\w+::)+//;
11581 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011582 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11583 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011584 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011585 }
11586 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11587 and $Base_1{"Name"} ne $Base_2{"Name"})
11588 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011589 if($Level eq "Binary"
11590 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011591 {
11592 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11593 "Target"=>$Typedef_1{"Name"},
11594 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011595 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11596 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11597 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011598 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11599 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011600 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011601 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011602 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11603 {
11604 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11605 "Target"=>$Typedef_1{"Name"},
11606 "Type_Name"=>$Typedef_1{"Name"},
11607 "Old_Value"=>$Base_1{"Name"},
11608 "New_Value"=>$Base_2{"Name"} );
11609 }
11610 else
11611 {
11612 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11613 "Target"=>$Typedef_1{"Name"},
11614 "Type_Name"=>$Typedef_1{"Name"},
11615 "Old_Value"=>$Base_1{"Name"},
11616 "New_Value"=>$Base_2{"Name"} );
11617 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011618 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011619 }
11620 }
11621 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11622 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011623 my $TT1 = $Type1_Pure{"Type"};
11624 my $TT2 = $Type2_Pure{"Type"};
11625
11626 if($TT1 ne $TT2
11627 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011628 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011629 my $Short1 = $Type1_Pure{"Name"};
11630 my $Short2 = $Type2_Pure{"Name"};
11631
11632 $Short1=~s/\A\Q$TT1\E //ig;
11633 $Short2=~s/\A\Q$TT2\E //ig;
11634
11635 if($Short1 eq $Short2)
11636 {
11637 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11638 "Target"=>$Type1_Pure{"Name"},
11639 "Type_Name"=>$Type1_Pure{"Name"},
11640 "Old_Value"=>lc($Type1_Pure{"Type"}),
11641 "New_Value"=>lc($Type2_Pure{"Type"}) );
11642 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011643 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011644 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011645 return %SubProblems;
11646 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011647 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011648 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11649 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11650 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11651 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011652 if($Level eq "Binary"
11653 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011654 {
11655 my $ProblemKind = "DataType_Size";
11656 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011657 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011658 {
11659 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11660 $ProblemKind = "Size_Of_Copying_Class";
11661 }
11662 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11663 {
11664 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11665 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11666 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011667 else
11668 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011669 # descreased size of allocable class
11670 # it has no special effects
11671 }
11672 }
11673 }
11674 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11675 "Target"=>$Type1_Pure{"Name"},
11676 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011677 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
11678 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE,
11679 "InitialType_Type"=>$Type1_Pure{"Type"} );
11680 }
11681 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011682 if(defined $Type1_Pure{"BaseType"}
11683 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011684 { # checking base types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011685 %Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011686 foreach my $Sub_SubProblemType (keys(%Sub_SubProblems))
11687 {
11688 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems{$Sub_SubProblemType}}))
11689 {
11690 foreach my $Attr (keys(%{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}})) {
11691 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr} = $Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr};
11692 }
11693 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{"InitialType_Type"} = $Type1_Pure{"Type"};
11694 }
11695 }
11696 }
11697 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11698 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11699 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11700 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11701 { # detect removed and renamed fields
11702 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11703 next if(not $Member_Name);
11704 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);
11705 if($MemberPair_Pos eq "lost")
11706 {
11707 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11708 {
11709 if(isUnnamed($Member_Name))
11710 { # support for old-version dumps
11711 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011712 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011713 next;
11714 }
11715 }
11716 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11717 { # renamed
11718 $RenamedField{$Member_Pos}=$RenamedTo;
11719 $RenamedField_Rev{$NameToPosB{$RenamedTo}}=$Member_Name;
11720 }
11721 else
11722 { # removed
11723 $RemovedField{$Member_Pos}=1;
11724 }
11725 }
11726 elsif($Type1_Pure{"Type"} eq "Enum")
11727 {
11728 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11729 next if($Member_Value1 eq "");
11730 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11731 if($MemberPair_Pos ne "lost")
11732 { # renamed
11733 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11734 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11735 if($MemberPair_Pos_Rev eq "lost")
11736 {
11737 $RenamedField{$Member_Pos}=$RenamedTo;
11738 $RenamedField_Rev{$NameToPosB{$RenamedTo}}=$Member_Name;
11739 }
11740 else {
11741 $RemovedField{$Member_Pos}=1;
11742 }
11743 }
11744 else
11745 { # removed
11746 $RemovedField{$Member_Pos}=1;
11747 }
11748 }
11749 }
11750 else
11751 { # related
11752 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11753 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11754 }
11755 }
11756 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11757 { # detect added fields
11758 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11759 next if(not $Member_Name);
11760 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);
11761 if($MemberPair_Pos eq "lost")
11762 {
11763 if(isUnnamed($Member_Name))
11764 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011765 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011766 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011767 next;
11768 }
11769 }
11770 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11771 {
11772 if(not $RenamedField_Rev{$Member_Pos})
11773 { # added
11774 $AddedField{$Member_Pos}=1;
11775 }
11776 }
11777 }
11778 }
11779 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11780 { # detect moved fields
11781 my (%RelPos, %RelPosName, %AbsPos) = ();
11782 my $Pos = 0;
11783 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11784 { # relative positions in 1st version
11785 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11786 next if(not $Member_Name);
11787 if(not $RemovedField{$Member_Pos})
11788 { # old type without removed fields
11789 $RelPos{1}{$Member_Name}=$Pos;
11790 $RelPosName{1}{$Pos} = $Member_Name;
11791 $AbsPos{1}{$Pos++} = $Member_Pos;
11792 }
11793 }
11794 $Pos = 0;
11795 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11796 { # relative positions in 2nd version
11797 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11798 next if(not $Member_Name);
11799 if(not $AddedField{$Member_Pos})
11800 { # new type without added fields
11801 $RelPos{2}{$Member_Name}=$Pos;
11802 $RelPosName{2}{$Pos} = $Member_Name;
11803 $AbsPos{2}{$Pos++} = $Member_Pos;
11804 }
11805 }
11806 foreach my $Member_Name (keys(%{$RelPos{1}}))
11807 {
11808 my $RPos1 = $RelPos{1}{$Member_Name};
11809 my $AbsPos1 = $NameToPosA{$Member_Name};
11810 my $Member_Name2 = $Member_Name;
11811 if(my $RenamedTo = $RenamedField{$AbsPos1})
11812 { # renamed
11813 $Member_Name2 = $RenamedTo;
11814 }
11815 my $RPos2 = $RelPos{2}{$Member_Name2};
11816 if($RPos2 ne "" and $RPos1 ne $RPos2)
11817 { # different relative positions
11818 my $AbsPos2 = $NameToPosB{$Member_Name2};
11819 if($AbsPos1 ne $AbsPos2)
11820 { # different absolute positions
11821 my $ProblemType = "Moved_Field";
11822 if(not isPublic(\%Type1_Pure, $AbsPos1))
11823 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011824 if($Level eq "Source") {
11825 next;
11826 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011827 $ProblemType = "Moved_Private_Field";
11828 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011829 if($Level eq "Binary"
11830 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011831 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011832 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011833 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011834 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011835 if($MemSize1 ne $MemSize2) {
11836 $ProblemType .= "_And_Size";
11837 }
11838 }
11839 if($ProblemType eq "Moved_Private_Field") {
11840 next;
11841 }
11842 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11843 "Target"=>$Member_Name,
11844 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011845 "Old_Value"=>$RPos1,
11846 "New_Value"=>$RPos2 );
11847 }
11848 }
11849 }
11850 }
11851 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011852 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011853 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11854 next if(not $Member_Name);
11855 if(my $RenamedTo = $RenamedField{$Member_Pos})
11856 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011857 if(defined $Constants{2}{$Member_Name})
11858 {
11859 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11860 { # define OLD NEW
11861 next; # Safe
11862 }
11863 }
11864
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011865 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11866 {
11867 if(isPublic(\%Type1_Pure, $Member_Pos))
11868 {
11869 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11870 "Target"=>$Member_Name,
11871 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011872 "Old_Value"=>$Member_Name,
11873 "New_Value"=>$RenamedTo );
11874 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011875 elsif(isReserved($Member_Name))
11876 {
11877 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11878 "Target"=>$Member_Name,
11879 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011880 "Old_Value"=>$Member_Name,
11881 "New_Value"=>$RenamedTo );
11882 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011883 }
11884 elsif($Type1_Pure{"Type"} eq "Enum")
11885 {
11886 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11887 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11888 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011889 "Old_Value"=>$Member_Name,
11890 "New_Value"=>$RenamedTo );
11891 }
11892 }
11893 elsif($RemovedField{$Member_Pos})
11894 { # removed
11895 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11896 {
11897 my $ProblemType = "Removed_Field";
11898 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011899 or isUnnamed($Member_Name))
11900 {
11901 if($Level eq "Source") {
11902 next;
11903 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011904 $ProblemType = "Removed_Private_Field";
11905 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011906 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011907 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011908 {
11909 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11910 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011911 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 +040011912 { # changed offset
11913 $ProblemType .= "_And_Layout";
11914 }
11915 }
11916 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11917 { # affected size
11918 $ProblemType .= "_And_Size";
11919 }
11920 }
11921 if($ProblemType eq "Removed_Private_Field") {
11922 next;
11923 }
11924 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11925 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011926 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011927 }
11928 elsif($Type2_Pure{"Type"} eq "Union")
11929 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011930 if($Level eq "Binary"
11931 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011932 {
11933 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11934 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011935 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011936 }
11937 else
11938 {
11939 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11940 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011941 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011942 }
11943 }
11944 elsif($Type1_Pure{"Type"} eq "Enum")
11945 {
11946 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11947 "Target"=>$Member_Name,
11948 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011949 "Old_Value"=>$Member_Name );
11950 }
11951 }
11952 else
11953 { # changed
11954 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11955 if($Type1_Pure{"Type"} eq "Enum")
11956 {
11957 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11958 next if($Member_Value1 eq "");
11959 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11960 next if($Member_Value2 eq "");
11961 if($Member_Value1 ne $Member_Value2)
11962 {
11963 my $ProblemType = "Enum_Member_Value";
11964 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11965 $ProblemType = "Enum_Last_Member_Value";
11966 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011967 if($SkipConstants{1}{$Member_Name}) {
11968 $ProblemType = "Enum_Private_Member_Value";
11969 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011970 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11971 "Target"=>$Member_Name,
11972 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011973 "Old_Value"=>$Member_Value1,
11974 "New_Value"=>$Member_Value2 );
11975 }
11976 }
11977 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11978 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011979 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
11980 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
11981
11982 if($Access1 ne "private"
11983 and $Access2 eq "private")
11984 {
11985 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
11986 "Target"=>$Member_Name,
11987 "Type_Name"=>$Type1_Pure{"Name"});
11988 }
11989 elsif($Access1 ne "protected"
11990 and $Access1 ne "private"
11991 and $Access2 eq "protected")
11992 {
11993 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
11994 "Target"=>$Member_Name,
11995 "Type_Name"=>$Type1_Pure{"Name"});
11996 }
11997
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011998 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
11999 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012000 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012001 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12002 $SizeV1 = $BSize1;
12003 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012004 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012005 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12006 $SizeV2 = $BSize2;
12007 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012008 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12009 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012010 if($Level eq "Binary"
12011 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012012 {
12013 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12014 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12015 { # field size change (including anon-structures and unions)
12016 # - same types
12017 # - unnamed types
12018 # - bitfields
12019 my $ProblemType = "Field_Size";
12020 if(not isPublic(\%Type1_Pure, $Member_Pos)
12021 or isUnnamed($Member_Name))
12022 { # should not be accessed by applications, goes to "Low Severity"
12023 # example: "abidata" members in GStreamer types
12024 $ProblemType = "Private_".$ProblemType;
12025 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012026 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 +040012027 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012028 if($Type2_Pure{"Type"} ne "Union"
12029 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012030 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012031 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 +040012032 { # changed offset
12033 $ProblemType .= "_And_Layout";
12034 }
12035 }
12036 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12037 $ProblemType .= "_And_Type_Size";
12038 }
12039 }
12040 if($ProblemType eq "Private_Field_Size")
12041 { # private field size with no effect
12042 $ProblemType = "";
12043 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012044 if($ProblemType eq "Field_Size")
12045 {
12046 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12047 { # Low severity
12048 $ProblemType = "Struct_Field_Size_Increased";
12049 }
12050 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012051 if($ProblemType)
12052 { # register a problem
12053 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12054 "Target"=>$Member_Name,
12055 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012056 "Old_Size"=>$SizeV1,
12057 "New_Size"=>$SizeV2);
12058 }
12059 }
12060 }
12061 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12062 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12063 { # do NOT check bitfield type changes
12064 next;
12065 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012066 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012067 {
12068 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12069 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12070 {
12071 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12072 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012073 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012074 }
12075 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12076 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12077 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012078 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012079 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012080 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012081 }
12082 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012083 %Sub_SubProblems = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012084 foreach my $ProblemType (keys(%Sub_SubProblems))
12085 {
12086 my $Old_Value = $Sub_SubProblems{$ProblemType}{"Old_Value"};
12087 my $New_Value = $Sub_SubProblems{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012088
12089 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012090 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012091 or $ProblemType eq "Field_Type_And_Size"
12092 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012093 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012094 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012095 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012096 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012097 %{$Sub_SubProblems{"Field_Became_Volatile"}} = %{$Sub_SubProblems{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012098 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012099 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
12100 %{$Sub_SubProblems{"Field_Became_Non_Volatile"}} = %{$Sub_SubProblems{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012101 }
12102 }
12103 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12104 {
12105 if($RA==2) {
12106 %{$Sub_SubProblems{"Field_Added_Const"}} = %{$Sub_SubProblems{$ProblemType}};
12107 }
12108 else {
12109 %{$Sub_SubProblems{"Field_Became_Const"}} = %{$Sub_SubProblems{$ProblemType}};
12110 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012111 }
12112 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12113 {
12114 if($RR==2) {
12115 %{$Sub_SubProblems{"Field_Removed_Const"}} = %{$Sub_SubProblems{$ProblemType}};
12116 }
12117 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012118 %{$Sub_SubProblems{"Field_Became_Non_Const"}} = %{$Sub_SubProblems{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012119 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012120 }
12121 }
12122 }
12123
12124 if($Level eq "Source")
12125 {
12126 foreach my $ProblemType (keys(%Sub_SubProblems))
12127 {
12128 my $Old_Value = $Sub_SubProblems{$ProblemType}{"Old_Value"};
12129 my $New_Value = $Sub_SubProblems{$ProblemType}{"New_Value"};
12130
12131 if($ProblemType eq "Field_Type")
12132 {
12133 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012134 delete($Sub_SubProblems{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012135 }
12136 }
12137 }
12138 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012139
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012140 foreach my $ProblemType (keys(%Sub_SubProblems))
12141 {
12142 my $ProblemType_Init = $ProblemType;
12143 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012144 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012145 if(not isPublic(\%Type1_Pure, $Member_Pos)
12146 or isUnnamed($Member_Name)) {
12147 $ProblemType = "Private_".$ProblemType;
12148 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012149 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 +040012150 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012151 if($Type2_Pure{"Type"} ne "Union"
12152 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012153 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012154 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 +040012155 { # changed offset
12156 $ProblemType .= "_And_Layout";
12157 }
12158 }
12159 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12160 $ProblemType .= "_And_Type_Size";
12161 }
12162 }
12163 }
12164 else
12165 {
12166 if(not isPublic(\%Type1_Pure, $Member_Pos)
12167 or isUnnamed($Member_Name)) {
12168 next;
12169 }
12170 }
12171 if($ProblemType eq "Private_Field_Type_And_Size")
12172 { # private field change with no effect
12173 next;
12174 }
12175 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12176 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012177 "Type_Name"=>$Type1_Pure{"Name"});
12178
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012179 foreach my $Attr (keys(%{$Sub_SubProblems{$ProblemType_Init}}))
12180 { # other properties
12181 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubProblems{$ProblemType_Init}{$Attr};
12182 }
12183 }
12184 if(not isPublic(\%Type1_Pure, $Member_Pos))
12185 { # do NOT check internal type changes
12186 next;
12187 }
12188 if($MemberType1_Id and $MemberType2_Id)
12189 {# checking member type changes (replace)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012190 %Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012191 foreach my $Sub_SubProblemType (keys(%Sub_SubProblems))
12192 {
12193 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems{$Sub_SubProblemType}}))
12194 {
12195 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12196 $SubProblems{$Sub_SubProblemType}{$NewLocation}{"IsInTypeInternals"}=1;
12197 foreach my $Attr (keys(%{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}})) {
12198 $SubProblems{$Sub_SubProblemType}{$NewLocation}{$Attr} = $Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr};
12199 }
12200 if($Sub_SubLocation!~/\-\>/) {
12201 $SubProblems{$Sub_SubProblemType}{$NewLocation}{"Start_Type_Name"} = $MemberType1_Name;
12202 }
12203 }
12204 }
12205 }
12206 }
12207 }
12208 }
12209 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12210 { # checking added members, public and private
12211 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12212 next if(not $Member_Name);
12213 if($AddedField{$Member_Pos})
12214 { # added
12215 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12216 {
12217 my $ProblemType = "Added_Field";
12218 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012219 or isUnnamed($Member_Name))
12220 {
12221 if($Level eq "Source") {
12222 next;
12223 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012224 $ProblemType = "Added_Private_Field";
12225 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012226 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012227 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012228 {
12229 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12230 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012231 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 +040012232 { # changed offset
12233 $ProblemType .= "_And_Layout";
12234 }
12235 }
12236 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12237 $ProblemType .= "_And_Size";
12238 }
12239 }
12240 if($ProblemType eq "Added_Private_Field")
12241 { # skip added private fields
12242 next;
12243 }
12244 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12245 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012246 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012247 }
12248 elsif($Type2_Pure{"Type"} eq "Union")
12249 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012250 if($Level eq "Binary"
12251 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012252 {
12253 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12254 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012255 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012256 }
12257 else
12258 {
12259 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12260 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012261 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012262 }
12263 }
12264 elsif($Type2_Pure{"Type"} eq "Enum")
12265 {
12266 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12267 next if($Member_Value eq "");
12268 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12269 "Target"=>$Member_Name,
12270 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012271 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012272 }
12273 }
12274 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012275 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012276 pop(@RecurTypes);
12277 return %SubProblems;
12278}
12279
12280sub isUnnamed($) {
12281 return $_[0]=~/\Aunnamed\d+\Z/;
12282}
12283
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012284sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012285{
12286 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012287 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12288 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12289 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12290 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012291 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012292 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012293 }
12294 return $TypeName;
12295}
12296
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012297sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012298{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012299 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012300 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012301 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12302 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012303 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012304 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12305 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012306 return () if(not $Type{"Type"});
12307 if($Type{"Type"} ne $Type_Type)
12308 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012309 return () if(not $Type{"BaseType"});
12310 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012311 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012312 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012313 return %Type;
12314}
12315
12316my %TypeSpecAttributes = (
12317 "Const" => 1,
12318 "Volatile" => 1,
12319 "ConstVolatile" => 1,
12320 "Restrict" => 1,
12321 "Typedef" => 1
12322);
12323
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012324sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012325{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012326 my ($TypeId, $Info) = @_;
12327 if(not $TypeId or not $Info
12328 or not $Info->{$TypeId}) {
12329 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012330 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012331 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12332 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12333 }
12334 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012335 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012336 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012337 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012338 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012339 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012340 return %Type;
12341}
12342
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012343sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012344{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012345 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012346 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012347 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12348 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012349 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012350 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12351 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012352 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12353 my $PLevel = 0;
12354 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12355 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012356 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012357 return $PLevel if(not $Type{"BaseType"});
12358 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12359 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12360 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012361}
12362
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012363sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012364{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012365 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012366 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012367 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12368 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012369 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012370 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12371 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012372 return %Type if(not $Type{"BaseType"});
12373 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012374 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012375 return %Type;
12376}
12377
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012378sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012379{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012380 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012381 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012382 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12383 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012384 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012385 my $Qual = "";
12386 if($Type{"Type"} eq "Pointer") {
12387 $Qual .= "*";
12388 }
12389 elsif($Type{"Type"} eq "Ref") {
12390 $Qual .= "&";
12391 }
12392 elsif($Type{"Type"} eq "ConstVolatile") {
12393 $Qual .= "const volatile";
12394 }
12395 elsif($Type{"Type"} eq "Const"
12396 or $Type{"Type"} eq "Volatile"
12397 or $Type{"Type"} eq "Restrict") {
12398 $Qual .= lc($Type{"Type"});
12399 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012400 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012401 return $BQual.$Qual;
12402}
12403
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012404sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012405{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012406 my ($TypeId, $Info) = @_;
12407 if(not $TypeId or not $Info
12408 or not $Info->{$TypeId}) {
12409 return ();
12410 }
12411 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012412 return %Type if(not $Type{"BaseType"});
12413 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012414 {
12415 if($Info->{$BTid}) {
12416 return %{$Info->{$BTid}};
12417 }
12418 else { # something is going wrong
12419 return ();
12420 }
12421 }
12422 else {
12423 return %Type;
12424 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012425}
12426
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012427sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012428{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012429 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012430 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012431 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12432 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012433}
12434
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012435sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012436{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012437 my $Symbol = $_[0];
12438 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12439}
12440
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012441sub isInLineInst($$$) {
12442 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12443}
12444
12445sub isTemplateInstance($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012446{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012447 my ($Symbol, $SInfo, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012448 if($CheckObjectsOnly)
12449 {
12450 if($Symbol!~/\A(_Z|\?)/) {
12451 return 0;
12452 }
12453 if(my $Signature = $tr_name{$Symbol})
12454 {
12455 if(index($Signature,">")==-1) {
12456 return 0;
12457 }
12458 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
12459 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012460 if(index($ShortName,"<")!=-1
12461 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012462 return 1;
12463 }
12464 }
12465 }
12466 }
12467 else
12468 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012469 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012470 {
12471 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
12472 {
12473 if(index($ClassName,"<")!=-1) {
12474 return 1;
12475 }
12476 }
12477 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012478 if(my $ShortName = $SInfo->{"ShortName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012479 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012480 if(index($ShortName,"<")!=-1
12481 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012482 return 1;
12483 }
12484 }
12485 }
12486 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012487}
12488
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012489sub isTemplateSpec($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012490{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012491 my ($Symbol, $SInfo, $LibVersion) = @_;
12492 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012493 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012494 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012495 { # class specialization
12496 return 1;
12497 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012498 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012499 { # method specialization
12500 return 1;
12501 }
12502 }
12503 return 0;
12504}
12505
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012506sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012507{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012508 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012509 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012510 { # non-public global data
12511 return 0;
12512 }
12513 if($CheckObjectsOnly) {
12514 return 0 if($Symbol=~/\A(_init|_fini)\Z/);
12515 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012516 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012517 { # support for old ABI dumps in --headers-only mode
12518 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12519 {
12520 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12521 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012522 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012523 if(not $PType or $PType eq "Unknown") {
12524 return 0;
12525 }
12526 }
12527 }
12528 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012529 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012530 {
12531 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012532 if($SkipSymbols{$LibVersion}{$Symbol})
12533 { # user defined symbols to ignore
12534 return 0;
12535 }
12536 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12537 if(not $NameSpace and $ClassId)
12538 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012539 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012540 }
12541 if($NameSpace)
12542 { # user defined namespaces to ignore
12543 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12544 return 0;
12545 }
12546 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12547 { # nested namespaces
12548 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12549 return 0;
12550 }
12551 }
12552 }
12553 if(my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
12554 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012555 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012556 { # --skip-headers or <skip_headers> (not <skip_including>)
12557 if($Skip==1) {
12558 return 0;
12559 }
12560 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012561 }
12562 if($SymbolsListPath and not $SymbolsList{$Symbol})
12563 { # user defined symbols
12564 return 0;
12565 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012566 if($SkipSymbolsListPath and $SkipSymbolsList{$Symbol})
12567 { # user defined symbols
12568 return 0;
12569 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012570 if($AppPath and not $SymbolsList_App{$Symbol})
12571 { # user defined symbols (in application)
12572 return 0;
12573 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012574 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12575 { # non-target symbols
12576 return 0;
12577 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012578 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012579 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012580 if($CheckObjectsOnly)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012581 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012582 if(isTemplateInstance($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012583 return 0;
12584 }
12585 }
12586 else
12587 {
12588 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012589 or isInLineInst($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012590 {
12591 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12592 { # inline virtual methods
12593 if($Type=~/InlineVirt/) {
12594 return 1;
12595 }
12596 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12597 if(not $Allocable)
12598 { # check bases
12599 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12600 {
12601 if(not isCopyingClass($DCId, $LibVersion))
12602 { # exists a derived class without default c-tor
12603 $Allocable=1;
12604 last;
12605 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012606 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012607 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012608 if(not $Allocable) {
12609 return 0;
12610 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012611 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012612 else
12613 { # inline non-virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012614 return 0;
12615 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012616 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012617 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012618 }
12619 }
12620 return 1;
12621}
12622
12623sub mergeImpl()
12624{
12625 my $DiffCmd = get_CmdPath("diff");
12626 if(not $DiffCmd) {
12627 exitStatus("Not_Found", "can't find \"diff\"");
12628 }
12629 foreach my $Interface (sort keys(%{$Symbol_Library{1}}))
12630 { # implementation changes
12631 next if($CompleteSignature{1}{$Interface}{"Private"});
12632 next if(not $CompleteSignature{1}{$Interface}{"Header"} and not $CheckObjectsOnly);
12633 next if(not $Symbol_Library{2}{$Interface} and not $Symbol_Library{2}{$SymVer{2}{$Interface}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012634 if(not symbolFilter($Interface, 1, "Affected", "Binary")) {
12635 next;
12636 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012637 my $Impl1 = canonifyImpl($Interface_Impl{1}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012638 next if(not $Impl1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012639 my $Impl2 = canonifyImpl($Interface_Impl{2}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012640 next if(not $Impl2);
12641 if($Impl1 ne $Impl2)
12642 {
12643 writeFile("$TMP_DIR/impl1", $Impl1);
12644 writeFile("$TMP_DIR/impl2", $Impl2);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012645 my $Diff = `$DiffCmd -rNau \"$TMP_DIR/impl1\" \"$TMP_DIR/impl2\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012646 $Diff=~s/(---|\+\+\+).+\n//g;
12647 $Diff=~s/[ ]{3,}/ /g;
12648 $Diff=~s/\n\@\@/\n \n\@\@/g;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012649 unlink("$TMP_DIR/impl1");
12650 unlink("$TMP_DIR/impl2");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040012651 %{$CompatProblems_Impl{$Interface}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012652 "Diff" => get_CodeView($Diff) );
12653 }
12654 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012655
12656 # clean memory
12657 %Interface_Impl = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012658}
12659
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012660sub canonifyImpl($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012661{
12662 my $FuncBody= $_[0];
12663 return "" if(not $FuncBody);
12664 $FuncBody=~s/0x[a-f\d]+/0x?/g;# addr
12665 $FuncBody=~s/((\A|\n)[a-z]+[\t ]+)[a-f\d]+([^x]|\Z)/$1?$3/g;# call, jump
12666 $FuncBody=~s/# [a-f\d]+ /# ? /g;# call, jump
12667 $FuncBody=~s/%([a-z]+[a-f\d]*)/\%reg/g;# registers
12668 while($FuncBody=~s/\nnop[ \t]*(\n|\Z)/$1/g){};# empty op
12669 $FuncBody=~s/<.+?\.cpp.+?>/<name.cpp>/g;
12670 $FuncBody=~s/(\A|\n)[a-f\d]+ </$1? </g;# 5e74 <_ZN...
12671 $FuncBody=~s/\.L\d+/.L/g;
12672 $FuncBody=~s/#(-?)\d+/#$1?/g;# r3, [r3, #120]
12673 $FuncBody=~s/[\n]{2,}/\n/g;
12674 return $FuncBody;
12675}
12676
12677sub get_CodeView($)
12678{
12679 my $Code = $_[0];
12680 my $View = "";
12681 foreach my $Line (split(/\n/, $Code))
12682 {
12683 if($Line=~s/\A(\+|-)/$1 /g)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012684 { # bold line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012685 $View .= "<tr><td><b>".htmlSpecChars($Line)."</b></td></tr>\n";
12686 }
12687 else {
12688 $View .= "<tr><td>".htmlSpecChars($Line)."</td></tr>\n";
12689 }
12690 }
12691 return "<table class='code_view'>$View</table>\n";
12692}
12693
12694sub getImplementations($$)
12695{
12696 my ($LibVersion, $Path) = @_;
12697 return if(not $LibVersion or not -e $Path);
12698 if($OSgroup eq "macos")
12699 {
12700 my $OtoolCmd = get_CmdPath("otool");
12701 if(not $OtoolCmd) {
12702 exitStatus("Not_Found", "can't find \"otool\"");
12703 }
12704 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012705 foreach my $Line (split(/\n/, `$OtoolCmd -tv \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012706 {
12707 if($Line=~/\A\s*_(\w+)\s*:/i) {
12708 $CurInterface = $1;
12709 }
12710 elsif($Line=~/\A\s*[\da-z]+\s+(.+?)\Z/i) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012711 $Interface_Impl{$LibVersion}{$CurInterface} .= $1."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012712 }
12713 }
12714 }
12715 else
12716 {
12717 my $ObjdumpCmd = get_CmdPath("objdump");
12718 if(not $ObjdumpCmd) {
12719 exitStatus("Not_Found", "can't find \"objdump\"");
12720 }
12721 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012722 foreach my $Line (split(/\n/, `$ObjdumpCmd -d \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012723 {
12724 if($Line=~/\A[\da-z]+\s+<(\w+)>/i) {
12725 $CurInterface = $1;
12726 }
12727 else
12728 { # x86: 51fa:(\t)89 e5 (\t)mov %esp,%ebp
12729 # arm: 5020:(\t)e24cb004(\t)sub(\t)fp, ip, #4(\t); 0x4
12730 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 +040012731 $Interface_Impl{$LibVersion}{$CurInterface} .= $2."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012732 }
12733 }
12734 }
12735 }
12736}
12737
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012738sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012739{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012740 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012741 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12742 {
12743 if(link_symbol($Symbol, 1, "+Deps"))
12744 { # linker can find a new symbol
12745 # in the old-version library
12746 # So, it's not a new symbol
12747 next;
12748 }
12749 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012750 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012751 next;
12752 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012753 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012754 }
12755}
12756
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012757sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012758{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012759 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012760 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12761 {
12762 if($CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012763 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012764 }
12765 if(link_symbol($Symbol, 2, "+Deps"))
12766 { # linker can find an old symbol
12767 # in the new-version library
12768 next;
12769 }
12770 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012771 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012772 next;
12773 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012774 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012775 }
12776}
12777
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012778sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012779{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012780 my $Level = $_[0];
12781 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012782 { # checking added symbols
12783 next if($CompleteSignature{2}{$Symbol}{"Private"});
12784 next if(not $CompleteSignature{2}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012785 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012786 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012787 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012788 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012789 { # checking removed symbols
12790 next if($CompleteSignature{1}{$Symbol}{"Private"});
12791 next if(not $CompleteSignature{1}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012792 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012793 { # skip v-tables for templates, that should not be imported by applications
12794 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012795 if(my $CName = $VTableClass{$Symbol})
12796 {
12797 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12798 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012799 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012800 next;
12801 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012802 }
12803 }
12804 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012805 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012806 }
12807 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12808 { # symbols for pure virtual methods cannot be called by clients
12809 next;
12810 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012811 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012812 }
12813}
12814
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012815sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012816{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012817 my ($LibVersion, $V) = @_;
12818 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12819 return $Cache{"checkDump"}{$LibVersion}{$V};
12820 }
12821 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012822}
12823
12824sub detectAdded_H($)
12825{
12826 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012827 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12828 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012829 if($Level eq "Source")
12830 { # remove symbol version
12831 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12832 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012833
12834 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12835 { # skip artificial constructors
12836 next;
12837 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012838 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012839 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12840 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012841 next;
12842 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012843 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012844 next;
12845 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012846 if(not defined $CompleteSignature{1}{$Symbol}
12847 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12848 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012849 if($UsedDump{2}{"SrcBin"})
12850 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012851 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012852 { # support for old and different (!) ABI dumps
12853 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12854 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012855 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012856 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012857 {
12858 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12859 {
12860 if($Lang eq "C")
12861 { # support for old ABI dumps: missed extern "C" functions
12862 next;
12863 }
12864 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012865 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012866 else
12867 {
12868 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012869 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012870 next;
12871 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012872 }
12873 }
12874 }
12875 }
12876 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012877 }
12878 }
12879}
12880
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012881sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012882{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012883 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012884 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12885 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012886 if($Level eq "Source")
12887 { # remove symbol version
12888 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12889 $Symbol=$SN;
12890 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012891 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12892 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012893 next;
12894 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012895 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012896 next;
12897 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012898 if(not defined $CompleteSignature{2}{$Symbol}
12899 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012900 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012901 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012902 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012903 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012904 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012905 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12906 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012907 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012908 if($CheckHeadersOnly)
12909 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012910 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12911 {
12912 if($Lang eq "C")
12913 { # support for old ABI dumps: missed extern "C" functions
12914 next;
12915 }
12916 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012917 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012918 else
12919 {
12920 if(not link_symbol($Symbol, 1, "-Deps"))
12921 { # skip removed inline symbols
12922 next;
12923 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012924 }
12925 }
12926 }
12927 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012928 if(not checkDump(1, "2.15"))
12929 {
12930 if($Symbol=~/_IT_E\Z/)
12931 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12932 next;
12933 }
12934 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012935 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12936 {
12937 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12938 {
12939 if(defined $Constants{2}{$Short})
12940 {
12941 my $Val = $Constants{2}{$Short}{"Value"};
12942 if(defined $Func_ShortName{2}{$Val})
12943 { # old name defined to new
12944 next;
12945 }
12946 }
12947 }
12948
12949 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012950 $RemovedInt{$Level}{$Symbol} = 1;
12951 if($Level eq "Source")
12952 { # search for a source-compatible equivalent
12953 setAlternative($Symbol, $Level);
12954 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012955 }
12956 }
12957}
12958
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012959sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012960{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012961 my $Level = $_[0];
12962 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012963 { # checking added symbols
12964 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012965 next if($CompleteSignature{2}{$Symbol}{"Private"});
12966 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012967 if($Level eq "Binary")
12968 {
12969 if($CompleteSignature{2}{$Symbol}{"InLine"})
12970 {
12971 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12972 { # skip inline non-virtual functions
12973 next;
12974 }
12975 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012976 }
12977 else
12978 { # Source
12979 if($SourceAlternative_B{$Symbol}) {
12980 next;
12981 }
12982 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012983 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012984 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012985 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012986 { # checking removed symbols
12987 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012988 next if($CompleteSignature{1}{$Symbol}{"Private"});
12989 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012990 if($Level eq "Binary")
12991 {
12992 if($CompleteSignature{1}{$Symbol}{"InLine"})
12993 {
12994 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
12995 { # skip inline non-virtual functions
12996 next;
12997 }
12998 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012999 }
13000 else
13001 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013002 if(my $Alt = $SourceAlternative{$Symbol})
13003 {
13004 if(defined $CompleteSignature{1}{$Alt}
13005 and $CompleteSignature{1}{$Symbol}{"Const"})
13006 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013007 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013008 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013009 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013010 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013011 }
13012 else
13013 { # do NOT show removed symbol
13014 next;
13015 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013016 }
13017 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013018 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013019 }
13020}
13021
13022sub addParamNames($)
13023{
13024 my $LibraryVersion = $_[0];
13025 return if(not keys(%AddIntParams));
13026 my $SecondVersion = $LibraryVersion==1?2:1;
13027 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13028 {
13029 next if(not keys(%{$AddIntParams{$Interface}}));
13030 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013031 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013032 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13033 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013034 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013035 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13036 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13037 {
13038 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13039 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13040 }
13041 }
13042 else {
13043 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13044 }
13045 }
13046 }
13047 }
13048}
13049
13050sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013051{ # detect changed typedefs to show
13052 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013053 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13054 {
13055 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013056 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13057 if(not $BName1 or isAnon($BName1)) {
13058 next;
13059 }
13060 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13061 if(not $BName2 or isAnon($BName2)) {
13062 next;
13063 }
13064 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013065 $ChangedTypedef{$Typedef} = 1;
13066 }
13067 }
13068}
13069
13070sub get_symbol_suffix($$)
13071{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013072 my ($Symbol, $Full) = @_;
13073 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013074 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013075 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013076 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013077 if(not $Full) {
13078 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13079 }
13080 return $Suffix;
13081}
13082
13083sub get_symbol_prefix($$)
13084{
13085 my ($Symbol, $LibVersion) = @_;
13086 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13087 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13088 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013089 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013090 }
13091 return $ShortName;
13092}
13093
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013094sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013095{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013096 my $Symbol = $_[0];
13097 my $PSymbol = $Symbol;
13098 if(not defined $CompleteSignature{2}{$PSymbol}
13099 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13100 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13101 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013102 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013103 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013104 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013105 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013106 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13107 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013108 {
13109 if(defined $CompleteSignature{2}{$PSymbol}
13110 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13111 {
13112 $SourceAlternative{$Symbol} = $PSymbol;
13113 $SourceAlternative_B{$PSymbol} = $Symbol;
13114 if(not defined $CompleteSignature{1}{$PSymbol}
13115 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13116 $SourceReplacement{$Symbol} = $PSymbol;
13117 }
13118 }
13119 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013120 }
13121 else
13122 {
13123 foreach my $Sp ("KV", "VK", "K", "V")
13124 {
13125 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13126 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13127 {
13128 if(defined $CompleteSignature{2}{$PSymbol}
13129 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13130 {
13131 $SourceAlternative{$Symbol} = $PSymbol;
13132 $SourceAlternative_B{$PSymbol} = $Symbol;
13133 if(not defined $CompleteSignature{1}{$PSymbol}
13134 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13135 $SourceReplacement{$Symbol} = $PSymbol;
13136 }
13137 }
13138 }
13139 $PSymbol = $Symbol;
13140 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013141 }
13142 }
13143 }
13144 return "";
13145}
13146
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013147sub getSymKind($$)
13148{
13149 my ($Symbol, $LibVersion) = @_;
13150 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13151 {
13152 return "Global_Data";
13153 }
13154 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13155 {
13156 return "Method";
13157 }
13158 return "Function";
13159}
13160
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013161sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013162{
13163 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013164 my %SubProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013165
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013166 mergeBases($Level);
13167
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013168 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013169 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013170 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013171 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013172 next;
13173 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013174 if(defined $CompleteSignature{1}{$Symbol}
13175 and $CompleteSignature{1}{$Symbol}{"Header"})
13176 { # double-check added symbol
13177 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013178 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013179 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013180 next;
13181 }
13182 if($Symbol=~/\A(_Z|\?)/)
13183 { # C++
13184 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13185 }
13186 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13187 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013188 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13189 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013190 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013191 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013192 {
13193 if($TName_Tid{1}{$AffectedClass_Name})
13194 { # class should exist in previous version
13195 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13196 { # old v-table is NOT copied by old applications
13197 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13198 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013199 "Target"=>get_Signature($Symbol, 2),
13200 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013201 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013202 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013203 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013204 }
13205 }
13206 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013207 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13208 { # check all removed exported symbols
13209 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013210 next;
13211 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013212 if(defined $CompleteSignature{2}{$Symbol}
13213 and $CompleteSignature{2}{$Symbol}{"Header"})
13214 { # double-check removed symbol
13215 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013216 }
13217 if($CompleteSignature{1}{$Symbol}{"Private"})
13218 { # skip private methods
13219 next;
13220 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013221 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013222 next;
13223 }
13224 $CheckedSymbols{$Level}{$Symbol} = 1;
13225 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13226 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013227 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13228 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013229 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013230 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13231 {
13232 if($TName_Tid{2}{$AffectedClass_Name})
13233 { # class should exist in newer version
13234 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13235 { # old v-table is NOT copied by old applications
13236 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13237 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013238 "Target"=>get_Signature($OverriddenMethod, 1),
13239 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013240 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013241 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013242 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013243 }
13244 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013245 if($Level eq "Binary"
13246 and $OSgroup eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013247 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013248 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013249 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013250 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013251 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013252 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013253 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013254 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013255 {
13256 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13257 "Target"=>$tr_name{$Symbol},
13258 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013259 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013260 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013261 else
13262 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013263 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013264 "Target"=>$tr_name{$Symbol},
13265 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013266 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013267 }
13268 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013269 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013270 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013271 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013272 {
13273 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13274 "Target"=>$tr_name{$Symbol},
13275 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013276 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013277 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013278 else
13279 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013280 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013281 "Target"=>$tr_name{$Symbol},
13282 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013283 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013284 }
13285 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013286 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13287 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13288 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13289 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13290 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013291 {
13292 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013293 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013294 $ProblemType = "Global_Data_Symbol_Changed_Type";
13295 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013296 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13297 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013298 "Old_Type"=>$RTName1,
13299 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013300 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013301 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013302 }
13303 }
13304 }
13305 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013306 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013307 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013308 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013309 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013310 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013311 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013312 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013313 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13314 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013315 if($Symbol=~/(C1E|C2E)/)
13316 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013317 my $CtorType = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013318 $NewSym=~s/(C1E|C2E)/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013319 }
13320 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013321 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13322 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013323 if($Symbol=~/(D0E|D1E|D2E)/)
13324 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013325 my $DtorType = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013326 $NewSym=~s/(D0E|D1E|D2E)/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013327 }
13328 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013329 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013330 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013331 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013332 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013333 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013334 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013335 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013336 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013337 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013338 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013339 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013340 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013341 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013342 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013343 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013344 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013345 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013346 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013347 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013348 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013349 "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 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013353 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013354 { # "volatile" to non-"volatile"
13355
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013356 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013357 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013358 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013359 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013360 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013361 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013362 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013363 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013364 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013365 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013366 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013367 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013368 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013369 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013370 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013371 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013372 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013373 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13374 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013375 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013376 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013377 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013378 }
13379 }
13380 }
13381 }
13382 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013383 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13384 { # checking symbols
13385 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13386 if($Level eq "Source")
13387 { # remove symbol version
13388 $Symbol=$SN;
13389 }
13390 else
13391 { # Binary
13392 if(not $SV)
13393 { # symbol without version
13394 if(my $VSym = $SymVer{1}{$Symbol})
13395 { # the symbol is linked with versioned symbol
13396 if($CompleteSignature{2}{$VSym}{"MnglName"})
13397 { # show report for symbol@ver only
13398 next;
13399 }
13400 elsif(not link_symbol($VSym, 2, "-Deps"))
13401 { # changed version: sym@v1 to sym@v2
13402 # do NOT show report for symbol
13403 next;
13404 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013405 }
13406 }
13407 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013408 my $PSymbol = $Symbol;
13409 if($Level eq "Source"
13410 and my $S = $SourceReplacement{$Symbol})
13411 { # take a source-compatible replacement function
13412 $PSymbol = $S;
13413 }
13414 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013415 { # private symbols
13416 next;
13417 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013418 if(not defined $CompleteSignature{1}{$Symbol}
13419 or not defined $CompleteSignature{2}{$PSymbol})
13420 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013421 next;
13422 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013423 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13424 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13425 { # no mangled name
13426 next;
13427 }
13428 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13429 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013430 { # without a header
13431 next;
13432 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013433
13434 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13435 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13436 { # became pure
13437 next;
13438 }
13439 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13440 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13441 { # became non-pure
13442 next;
13443 }
13444
13445 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13446 { # exported, target, inline virtual and pure virtual
13447 next;
13448 }
13449 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13450 { # exported, target, inline virtual and pure virtual
13451 next;
13452 }
13453
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013454 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013455 {
13456 if($CompleteSignature{1}{$Symbol}{"Data"}
13457 and $CompleteSignature{2}{$PSymbol}{"Data"})
13458 {
13459 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13460 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13461 if(defined $Value1)
13462 {
13463 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13464 if(defined $Value2)
13465 {
13466 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13467 if($Value1 ne $Value2)
13468 {
13469 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13470 "Old_Value"=>$Value1,
13471 "New_Value"=>$Value2,
13472 "Target"=>get_Signature($Symbol, 1) );
13473 }
13474 }
13475 }
13476 }
13477 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013478
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013479 if($CompleteSignature{2}{$PSymbol}{"Private"})
13480 {
13481 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13482 "Target"=>get_Signature_M($PSymbol, 2) );
13483 }
13484 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13485 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13486 {
13487 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13488 "Target"=>get_Signature_M($PSymbol, 2) );
13489 }
13490 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13491 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13492 {
13493 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13494 "Target"=>get_Signature_M($PSymbol, 2) );
13495 }
13496
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013497 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013498 mergeVirtualTables($Symbol, $Level);
13499
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013500 if($COMPILE_ERRORS)
13501 { # if some errors occurred at the compiling stage
13502 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013503 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013504 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013505 { # missed information about parameters in newer version
13506 next;
13507 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013508 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013509 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013510 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013511 next;
13512 }
13513 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013514 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013515 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013516 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013517 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13518 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013519 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13520 "Target"=>get_Signature($Symbol, 1)
13521 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013522 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013523 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013524 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13525 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013526 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013527 "Target"=>get_Signature($Symbol, 1)
13528 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013529 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013530 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13531 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013532 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013533 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013534 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013535 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13536 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13537 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013538 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013539 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013540 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13541 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013542 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013543 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013544 my $ProblemType = "Virtual_Method_Position";
13545 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13546 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013547 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013548 if(isUsedClass($Class_Id, 1, $Level))
13549 {
13550 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013551 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013552 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013553 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13554 next;
13555 }
13556 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013557 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013558 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13559 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013560 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013561 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013562 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013563 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013564 }
13565 }
13566 }
13567 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013568 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13569 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013570 { # do NOT check type changes in pure virtuals
13571 next;
13572 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013573 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013574 if($Symbol=~/\A(_Z|\?)/
13575 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013576 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013577 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013578 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013579 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013580 }
13581 }
13582 else
13583 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013584 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013585 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013586 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013587 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13588 last if($PType2_Name eq "...");
13589 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13590 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013591 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013592 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013593 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013594 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13595 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013596 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13597 $ParamPos_Prev = "lost";
13598 }
13599 }
13600 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013601 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013602 }
13603 if($ParamPos_Prev eq "lost")
13604 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013605 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013606 {
13607 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013608 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013609 $ProblemType = "Added_Unnamed_Parameter";
13610 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013611 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013612 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013613 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013614 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013615 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013616 }
13617 else
13618 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013619 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013620 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013621 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013622 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13623 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013624 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013625 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013626 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013627 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013628 "Target"=>$PName_Old,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013629 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013630 "Param_Type"=>$PType2_Name,
13631 "Old_Value"=>$PName_Old,
13632 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013633 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013634 }
13635 }
13636 else
13637 {
13638 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013639 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013640 $ProblemType = "Added_Middle_Unnamed_Parameter";
13641 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013642 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013643 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013644 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013645 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013646 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013647 }
13648 }
13649 }
13650 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013651 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013652 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013653 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013654 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013655 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013656 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013657 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013658 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013659 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013660 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13661 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013662 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013663 }
13664 }
13665 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013666 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013667 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013668 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013669 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13670 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013671 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13672 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013673 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013674 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013675 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013676 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13677 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013678 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13679 $ParamPos_New = "lost";
13680 }
13681 }
13682 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013683 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013684 }
13685 if($ParamPos_New eq "lost")
13686 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013687 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013688 {
13689 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013690 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013691 $ProblemType = "Removed_Unnamed_Parameter";
13692 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013693 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013694 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013695 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013696 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013697 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013698 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013699 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013700 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013701 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013702 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013703 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013704 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013705 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013706 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013707 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013708 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013709 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013710 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013711 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013712 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013713 "Old_Value"=>$PName,
13714 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013715 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013716 }
13717 }
13718 else
13719 {
13720 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013721 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013722 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13723 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013724 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013725 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013726 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013727 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013728 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013729 }
13730 }
13731 }
13732 }
13733 }
13734 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013735 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13736 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
13737 %SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013738
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013739 foreach my $SubProblemType (keys(%SubProblems))
13740 {
13741 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13742 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013743 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013744
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013745 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013746 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013747 if($SubProblemType eq "Return_Type_And_Size") {
13748 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13749 }
13750 elsif($SubProblemType eq "Return_Type_Format") {
13751 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13752 }
13753 else {
13754 $ProblemTypes{"Global_Data_Type"} = 1;
13755 }
13756
13757 # quals
13758 if($SubProblemType eq "Return_Type"
13759 or $SubProblemType eq "Return_Type_And_Size"
13760 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013761 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013762 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13763 { # const to non-const
13764 if($RR==2) {
13765 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13766 }
13767 else {
13768 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13769 }
13770 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013771 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013772 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13773 { # non-const to const
13774 if($RA==2) {
13775 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13776 }
13777 else {
13778 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13779 }
13780 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013781 }
13782 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013783 }
13784 else
13785 {
13786 # quals
13787 if($SubProblemType eq "Return_Type"
13788 or $SubProblemType eq "Return_Type_And_Size"
13789 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013790 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013791 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013792 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013793 if(addedQual($Old_Value, $New_Value, "volatile"))
13794 {
13795 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13796 if($Level ne "Source"
13797 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13798 $ProblemTypes{"Return_Type"} = 1;
13799 }
13800 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013801 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013802 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13803 {
13804 if($RA==2) {
13805 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13806 }
13807 else {
13808 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13809 }
13810 if($Level ne "Source"
13811 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13812 $ProblemTypes{"Return_Type"} = 1;
13813 }
13814 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013815 }
13816 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013817 if($Level eq "Binary"
13818 and not $CompleteSignature{1}{$Symbol}{"Data"})
13819 {
13820 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13821 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13822 { # if one of the architectures is unknown
13823 # then set other arhitecture to unknown too
13824 ($Arch1, $Arch2) = ("unknown", "unknown");
13825 }
13826 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013827 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013828 {
13829 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13830 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13831 }
13832 else
13833 {
13834 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13835 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13836 }
13837
13838 if($SubProblemType eq "Return_Type_Became_Void")
13839 {
13840 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13841 { # parameters stack has been affected
13842 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013843 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013844 }
13845 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013846 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013847 }
13848 }
13849 }
13850 elsif($SubProblemType eq "Return_Type_From_Void")
13851 {
13852 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13853 { # parameters stack has been affected
13854 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013855 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013856 }
13857 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013858 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013859 }
13860 }
13861 }
13862 elsif($SubProblemType eq "Return_Type"
13863 or $SubProblemType eq "Return_Type_And_Size"
13864 or $SubProblemType eq "Return_Type_Format")
13865 {
13866 if($Conv1{"Method"} ne $Conv2{"Method"})
13867 {
13868 if($Conv1{"Method"} eq "stack")
13869 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013870 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013871 }
13872 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013873 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013874 }
13875 }
13876 else
13877 {
13878 if($Conv1{"Method"} eq "reg")
13879 {
13880 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13881 {
13882 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013883 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013884 }
13885 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013886 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013887 }
13888 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013889 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013890 }
13891 }
13892 }
13893 }
13894 }
13895 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013896
13897 if(not keys(%ProblemTypes))
13898 { # default
13899 $ProblemTypes{$SubProblemType} = 1;
13900 }
13901
13902 foreach my $ProblemType (keys(%ProblemTypes))
13903 { # additional
13904 @{$CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013905 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013906 }
13907 if($ReturnType1_Id and $ReturnType2_Id)
13908 {
13909 @RecurTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013910 %SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013911
13912 if($CompleteSignature{1}{$Symbol}{"Data"})
13913 {
13914 if($Level eq "Binary")
13915 {
13916 if(get_PLevel($ReturnType1_Id, 1)==0)
13917 {
13918 foreach my $SubProblemType (keys(%SubProblems))
13919 { # add "Global_Data_Size" problem
13920 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13921 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
13922 if($SubProblemType eq "DataType_Size")
13923 { # add a new problem
13924 %{$SubProblems{"Global_Data_Size"}} = %{$SubProblems{$SubProblemType}};
13925 }
13926 }
13927 }
13928 if(not defined $SubProblems{"Global_Data_Size"})
13929 {
13930 if(defined $GlobalDataObject{1}{$Symbol}
13931 and defined $GlobalDataObject{2}{$Symbol})
13932 {
13933 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13934 my $New_Size = $GlobalDataObject{2}{$Symbol};
13935 if($Old_Size!=$New_Size)
13936 {
13937 %{$SubProblems{"Global_Data_Size"}{"retval"}} = (
13938 "Old_Size"=>$Old_Size*$BYTE_SIZE,
13939 "New_Size"=>$New_Size*$BYTE_SIZE );
13940 }
13941 }
13942 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013943 }
13944 }
13945 foreach my $SubProblemType (keys(%SubProblems))
13946 {
13947 foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}}))
13948 {
13949 my $NewLocation = ($SubLocation)?"retval->".$SubLocation:"retval";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013950 %{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013951 "Return_Type_Name"=>$TypeInfo{1}{$ReturnType1_Id}{"Name"} );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013952 @{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013953 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013954 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$ReturnType1_Id}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013955 }
13956 }
13957 }
13958 }
13959
13960 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013961 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13962 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13963 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013964 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013965 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013966 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13967 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013968 if($ThisPtr1_Id and $ThisPtr2_Id)
13969 {
13970 @RecurTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013971 %SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013972 foreach my $SubProblemType (keys(%SubProblems))
13973 {
13974 foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}}))
13975 {
13976 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013977 %{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013978 "Object_Type_Name"=>$TypeInfo{1}{$ObjTId1}{"Name"} );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013979 @{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013980 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013981 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$ObjTId1}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013982 }
13983 }
13984 }
13985 }
13986 }
13987 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013988 if($Level eq "Binary") {
13989 mergeVTables($Level);
13990 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013991 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
13992 $CheckedSymbols{$Level}{$Symbol} = 1;
13993 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013994}
13995
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013996sub rmQuals($$)
13997{
13998 my ($Value, $Qual) = @_;
13999 if(not $Qual) {
14000 return $Value;
14001 }
14002 if($Qual eq "all")
14003 { # all quals
14004 $Qual = "const|volatile|restrict";
14005 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014006 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014007 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014008 }
14009 return $Value;
14010}
14011
14012sub cmpBTypes($$$$)
14013{
14014 my ($T1, $T2, $V1, $V2) = @_;
14015 $T1 = uncover_typedefs($T1, $V1);
14016 $T2 = uncover_typedefs($T2, $V2);
14017 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14018}
14019
14020sub addedQual($$$)
14021{
14022 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014023 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014024}
14025
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014026sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014027{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014028 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014029 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014030}
14031
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014032sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014033{
14034 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14035 $Old_Value = uncover_typedefs($Old_Value, $V1);
14036 $New_Value = uncover_typedefs($New_Value, $V2);
14037 if($Old_Value eq $New_Value)
14038 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014039 return 0;
14040 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014041 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014042 { # without a qual
14043 return 0;
14044 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014045 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014046 { # became non-qual
14047 return 1;
14048 }
14049 else
14050 {
14051 my @BQ1 = getQualModel($Old_Value, $Qual);
14052 my @BQ2 = getQualModel($New_Value, $Qual);
14053 foreach (0 .. $#BQ1)
14054 { # removed qual
14055 if($BQ1[$_]==1
14056 and $BQ2[$_]!=1)
14057 {
14058 return 2;
14059 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014060 }
14061 }
14062 return 0;
14063}
14064
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014065sub getQualModel($$)
14066{
14067 my ($Value, $Qual) = @_;
14068 if(not $Qual) {
14069 return $Value;
14070 }
14071
14072 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014073 while($Value=~/(\w+)/ and $1 ne $Qual) {
14074 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014075 }
14076 $Value=~s/[^\*\&\w]+//g;
14077
14078 # modeling
14079 # int*const*const == 011
14080 # int**const == 001
14081 my @Model = ();
14082 my @Elems = split(/[\*\&]/, $Value);
14083 if(not @Elems) {
14084 return (0);
14085 }
14086 foreach (@Elems)
14087 {
14088 if($_ eq $Qual) {
14089 push(@Model, 1);
14090 }
14091 else {
14092 push(@Model, 0);
14093 }
14094 }
14095
14096 return @Model;
14097}
14098
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014099my %StringTypes = map {$_=>1} (
14100 "char*",
14101 "char const*"
14102);
14103
14104my %CharTypes = map {$_=>1} (
14105 "char",
14106 "char const"
14107);
14108
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014109sub showVal($$$)
14110{
14111 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014112 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014113 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014114 if(substr($Value, 0, 2) eq "_Z")
14115 {
14116 if(my $Unmangled = $tr_name{$Value}) {
14117 return $Unmangled;
14118 }
14119 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014120 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014121 { # strings
14122 return "\"$Value\"";
14123 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014124 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014125 { # characters
14126 return "\'$Value\'";
14127 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014128 if($Value eq "")
14129 { # other
14130 return "\'\'";
14131 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014132 return $Value;
14133}
14134
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014135sub getRegs($$$)
14136{
14137 my ($LibVersion, $Symbol, $Pos) = @_;
14138
14139 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14140 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014141 my %Regs = ();
14142 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14143 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014144 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014145 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14146 }
14147 }
14148
14149 return join(", ", sort keys(%Regs));
14150 }
14151
14152 return undef;
14153}
14154
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014155sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014156{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014157 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014158 if(not $Symbol) {
14159 return;
14160 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014161 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14162 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14163 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14164 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014165 if(not $PType1_Id
14166 or not $PType2_Id) {
14167 return;
14168 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014169
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014170 if(index($Symbol, "_Z")==0)
14171 { # do not merge "this"
14172 if($PName1 eq "this" or $PName2 eq "this") {
14173 return;
14174 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014175 }
14176
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014177 my %Type1 = get_Type($PType1_Id, 1);
14178 my %Type2 = get_Type($PType2_Id, 2);
14179 my %BaseType1 = get_BaseType($PType1_Id, 1);
14180 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014181 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014182
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014183 if($Level eq "Binary")
14184 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014185 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014186 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14187 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14188 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14189 {
14190 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014191 "Target"=>$PName1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014192 "Param_Pos"=>$ParamPos1 );
14193 }
14194 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14195 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14196 {
14197 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014198 "Target"=>$PName1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014199 "Param_Pos"=>$ParamPos1 );
14200 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014201 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014202
14203 if(defined $UsedDump{1}{"DWARF"}
14204 and defined $UsedDump{2}{"DWARF"})
14205 {
14206 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14207 {
14208 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14209 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
14210 if($Old_Regs and $New_Regs)
14211 {
14212 if($Old_Regs ne $New_Regs)
14213 {
14214 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14215 "Target"=>$PName1,
14216 "Param_Pos"=>$ParamPos1,
14217 "Old_Value"=>$Old_Regs,
14218 "New_Value"=>$New_Regs );
14219 }
14220 }
14221 elsif($Old_Regs and not $New_Regs)
14222 {
14223 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
14224 "Target"=>$PName1,
14225 "Param_Pos"=>$ParamPos1,
14226 "Old_Value"=>$Old_Regs );
14227 }
14228 elsif(not $Old_Regs and $New_Regs)
14229 {
14230 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14231 "Target"=>$PName1,
14232 "Param_Pos"=>$ParamPos1,
14233 "New_Value"=>$New_Regs );
14234 }
14235 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14236 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14237 {
14238 if($Old_Offset ne $New_Offset)
14239 {
14240 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14241 "Target"=>$PName1,
14242 "Param_Pos"=>$ParamPos1,
14243 "Old_Value"=>$Old_Offset,
14244 "New_Value"=>$New_Offset );
14245 }
14246 }
14247 }
14248 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014249 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014250 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14251 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014252 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014253 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014254 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14255 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014256 if(not checkDump(1, "2.13")
14257 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014258 { # support for old ABI dumps
14259 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014260 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014261 if($Type1{"Name"} eq "bool"
14262 and $Value_Old eq "false" and $Value_New eq "0")
14263 { # int class::method ( bool p = 0 );
14264 # old ABI dumps: "false"
14265 # new ABI dumps: "0"
14266 $Value_Old = "0";
14267 }
14268 }
14269 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014270 if(not checkDump(1, "2.18")
14271 and checkDump(2, "2.18"))
14272 { # support for old ABI dumps
14273 if(not defined $Value_Old
14274 and substr($Value_New, 0, 2) eq "_Z") {
14275 $Value_Old = $Value_New;
14276 }
14277 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014278 if(defined $Value_Old)
14279 {
14280 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14281 if(defined $Value_New)
14282 {
14283 $Value_New = showVal($Value_New, $PType2_Id, 2);
14284 if($Value_Old ne $Value_New)
14285 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014286 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014287 "Target"=>$PName1,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014288 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014289 "Old_Value"=>$Value_Old,
14290 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014291 }
14292 }
14293 else
14294 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014295 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014296 "Target"=>$PName1,
14297 "Param_Pos"=>$ParamPos1,
14298 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014299 }
14300 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014301 elsif(defined $Value_New)
14302 {
14303 $Value_New = showVal($Value_New, $PType2_Id, 2);
14304 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14305 "Target"=>$PName1,
14306 "Param_Pos"=>$ParamPos1,
14307 "New_Value"=>$Value_New );
14308 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014309 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014310
14311 if($ChkRnmd)
14312 {
14313 if($PName1 and $PName2 and $PName1 ne $PName2
14314 and $PType1_Id!=-1 and $PType2_Id!=-1
14315 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14316 { # except unnamed "..." value list (Id=-1)
14317 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14318 "Target"=>$PName1,
14319 "Param_Pos"=>$ParamPos1,
14320 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14321 "Old_Value"=>$PName1,
14322 "New_Value"=>$PName2,
14323 "New_Signature"=>get_Signature($Symbol, 2) );
14324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014325 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014326
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014327 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014328 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014329 foreach my $SubProblemType (keys(%SubProblems))
14330 { # add new problems, remove false alarms
14331 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14332 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014333
14334 # quals
14335 if($SubProblemType eq "Parameter_Type"
14336 or $SubProblemType eq "Parameter_Type_And_Size"
14337 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014338 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014339 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014340 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014341 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014342 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014343 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014344 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14345 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14346 }
14347 }
14348 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14349 {
14350 if(removedQual($Old_Value, $New_Value, "volatile")) {
14351 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014352 }
14353 }
14354 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14355 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14356 { # int to "int const"
14357 delete($SubProblems{$SubProblemType});
14358 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014359 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014360 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14361 { # "int const" to int
14362 delete($SubProblems{$SubProblemType});
14363 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014364 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14365 { # "const" to non-"const"
14366 if($RR==2) {
14367 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14368 }
14369 else {
14370 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14371 }
14372 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014373 }
14374 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014375
14376 if($Level eq "Source")
14377 {
14378 foreach my $SubProblemType (keys(%SubProblems))
14379 {
14380 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14381 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14382
14383 if($SubProblemType eq "Parameter_Type")
14384 {
14385 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14386 delete($SubProblems{$SubProblemType});
14387 }
14388 }
14389 }
14390 }
14391
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014392 foreach my $SubProblemType (keys(%SubProblems))
14393 { # modify/register problems
14394 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14395 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014396 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14397 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014398
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014399 my $NewProblemType = $SubProblemType;
14400 if($Old_Value eq "..." and $New_Value ne "...")
14401 { # change from "..." to "int"
14402 if($ParamPos1==0)
14403 { # ISO C requires a named argument before "..."
14404 next;
14405 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014406 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014407 }
14408 elsif($New_Value eq "..." and $Old_Value ne "...")
14409 { # change from "int" to "..."
14410 if($ParamPos2==0)
14411 { # ISO C requires a named argument before "..."
14412 next;
14413 }
14414 $NewProblemType = "Parameter_Became_VaList";
14415 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014416 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014417 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014418 {
14419 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014420 if($Arch1 eq "unknown"
14421 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014422 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014423 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014424 ($Arch1, $Arch2) = ("unknown", "unknown");
14425 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014426 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014427 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014428 { # real
14429 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14430 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14431 }
14432 else
14433 { # model
14434 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14435 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14436 }
14437 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014438 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014439 if($Conv1{"Method"} eq "stack")
14440 {
14441 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14442 $NewProblemType = "Parameter_Type_And_Stack";
14443 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014444 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014445 elsif($Conv1{"Method"} eq "reg")
14446 {
14447 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14448 $NewProblemType = "Parameter_Type_And_Register";
14449 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014450 }
14451 }
14452 else
14453 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014454 if($Conv1{"Method"} eq "stack") {
14455 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014456 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014457 elsif($Conv1{"Method"} eq "register") {
14458 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014459 }
14460 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014461 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14462 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014463 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014464 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014465 "Target"=>$PName1,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014466 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014467 "New_Signature"=>get_Signature($Symbol, 2) );
14468 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014469 }
14470 @RecurTypes = ();
14471 # checking type definition changes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014472 my %SubProblems_Merge = mergeTypes($PType1_Id, $PType2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014473 foreach my $SubProblemType (keys(%SubProblems_Merge))
14474 {
14475 foreach my $SubLocation (keys(%{$SubProblems_Merge{$SubProblemType}}))
14476 {
14477 my $NewProblemType = $SubProblemType;
14478 if($SubProblemType eq "DataType_Size")
14479 {
14480 my $InitialType_Type = $SubProblems_Merge{$SubProblemType}{$SubLocation}{"InitialType_Type"};
14481 if($InitialType_Type!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
14482 { # stack has been affected
14483 $NewProblemType = "DataType_Size_And_Stack";
14484 }
14485 }
14486 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014487 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014488 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014489 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014490 "Param_Name"=>$PName1 );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014491 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}}{keys(%{$SubProblems_Merge{$SubProblemType}{$SubLocation}})} = values %{$SubProblems_Merge{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014492 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014493 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$PType1_Id}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014494 }
14495 }
14496 }
14497}
14498
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014499sub find_ParamPair_Pos_byName($$$)
14500{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014501 my ($Name, $Symbol, $LibVersion) = @_;
14502 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014503 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014504 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14505 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014506 {
14507 return $ParamPos;
14508 }
14509 }
14510 return "lost";
14511}
14512
14513sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14514{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014515 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014516 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014517 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014518 {
14519 next if($Order eq "backward" and $ParamPos>$MediumPos);
14520 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014521 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14522 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014523 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014524 push(@Positions, $ParamPos);
14525 }
14526 }
14527 return @Positions;
14528}
14529
14530sub getTypeIdByName($$)
14531{
14532 my ($TypeName, $Version) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014533 return $TName_Tid{$Version}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014534}
14535
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014536sub diffTypes($$$)
14537{
14538 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14539 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14540 }
14541 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14542 { # skip recursive declarations
14543 return 0;
14544 }
14545
14546 pushType($_[0], $_[1], \@RecurTypes_Diff);
14547 my $Diff = diffTypes_I(@_);
14548 pop(@RecurTypes_Diff);
14549
14550 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14551}
14552
14553sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014554{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014555 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014556
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014557 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14558 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014559
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014560 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14561 { # equal types
14562 return 0;
14563 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014564 if($Type1_Pure{"Name"} eq "void")
14565 { # from void* to something
14566 return 0;
14567 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014568 if($Type1_Pure{"Name"}=~/\*/
14569 or $Type2_Pure{"Name"}=~/\*/)
14570 { # compared in detectTypeChange()
14571 return 0;
14572 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014573
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014574 my %FloatType = map {$_=>1} (
14575 "float",
14576 "double",
14577 "long double"
14578 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014579
14580 my $T1 = $Type1_Pure{"Type"};
14581 my $T2 = $Type2_Pure{"Type"};
14582
14583 if($T1 eq "Struct"
14584 and $T2 eq "Class")
14585 { # compare as data structures
14586 $T2 = "Struct";
14587 }
14588
14589 if($T1 eq "Class"
14590 and $T2 eq "Struct")
14591 { # compare as data structures
14592 $T1 = "Struct";
14593 }
14594
14595 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014596 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014597 if($T1 eq "Intrinsic"
14598 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014599 { # "int" to "enum"
14600 return 0;
14601 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014602 elsif($T2 eq "Intrinsic"
14603 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014604 { # "enum" to "int"
14605 return 0;
14606 }
14607 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014608 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014609 # ...
14610 return 1;
14611 }
14612 }
14613 else
14614 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014615 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014616 {
14617 if($FloatType{$Type1_Pure{"Name"}}
14618 or $FloatType{$Type2_Pure{"Name"}})
14619 { # "float" to "double"
14620 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014621 if($Level eq "Source")
14622 { # Safe
14623 return 0;
14624 }
14625 else {
14626 return 1;
14627 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014628 }
14629 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014630 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014631 {
14632 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14633 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014634 if(not @Membs1
14635 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014636 { # private
14637 return 0;
14638 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014639 if($#Membs1!=$#Membs2)
14640 { # different number of elements
14641 return 1;
14642 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014643 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014644 {
14645 foreach my $Pos (@Membs1)
14646 { # compare elements by name and value
14647 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14648 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14649 { # different names
14650 return 1;
14651 }
14652 }
14653 }
14654 else
14655 {
14656 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014657 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014658 if($Level eq "Source")
14659 {
14660 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14661 { # different names
14662 return 1;
14663 }
14664 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014665
14666 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14667 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14668
14669 if($MT1{"Name"} ne $MT2{"Name"}
14670 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14671 {
14672 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14673 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14674
14675 if($PL1 ne $PL2)
14676 { # different pointer level
14677 return 1;
14678 }
14679
14680 # compare base types
14681 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14682 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14683
14684 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14685 { # different types
14686 return 1;
14687 }
14688 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014689 }
14690 }
14691 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014692 else
14693 {
14694 # TODO: arrays, etc.
14695 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014696 }
14697 return 0;
14698}
14699
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014700sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014701{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014702 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014703 if(not $Type1_Id or not $Type2_Id) {
14704 return ();
14705 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014706 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014707 my %Type1 = get_Type($Type1_Id, 1);
14708 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014709 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14710 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14711 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14712 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 +040014713
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014714 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14715 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014716 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14717 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14718 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14719 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14720 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14721 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14722 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014723 if($Type1{"Name"} eq $Type2{"Name"})
14724 {
14725 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14726 { # will be reported in mergeTypes() as typedef problem
14727 return ();
14728 }
14729 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14730 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14731 if(%Typedef_1 and %Typedef_2)
14732 {
14733 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14734 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14735 { # const Typedef
14736 return ();
14737 }
14738 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014739 }
14740 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14741 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014742 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014743 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14744 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014745 {
14746 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14747 "Old_Value"=>$Type1_Base{"Name"},
14748 "New_Value"=>$Type2_Base{"Name"},
14749 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
14750 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
14751 "InitialType_Type"=>$Type1_Pure{"Type"});
14752 }
14753 else
14754 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014755 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014756 { # format change
14757 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14758 "Old_Value"=>$Type1_Base{"Name"},
14759 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014760 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
14761 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014762 "InitialType_Type"=>$Type1_Pure{"Type"});
14763 }
14764 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14765 {
14766 %{$LocalProblems{$Prefix."_BaseType"}}=(
14767 "Old_Value"=>$Type1_Base{"Name"},
14768 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014769 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
14770 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014771 "InitialType_Type"=>$Type1_Pure{"Type"});
14772 }
14773 }
14774 }
14775 }
14776 elsif($Type1{"Name"} ne $Type2{"Name"})
14777 { # type change
14778 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14779 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014780 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014781 and $Type1_Pure{"Name"} eq "void")
14782 {
14783 %{$LocalProblems{"Return_Type_From_Void"}}=(
14784 "New_Value"=>$Type2{"Name"},
14785 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
14786 "InitialType_Type"=>$Type1_Pure{"Type"});
14787 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014788 elsif($Prefix eq "Return"
14789 and $Type2_Pure{"Name"} eq "void")
14790 {
14791 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14792 "Old_Value"=>$Type1{"Name"},
14793 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14794 "InitialType_Type"=>$Type1_Pure{"Type"});
14795 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014796 else
14797 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014798 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014799 and $Type1{"Size"} and $Type2{"Size"}
14800 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014801 {
14802 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14803 "Old_Value"=>$Type1{"Name"},
14804 "New_Value"=>$Type2{"Name"},
14805 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14806 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
14807 "InitialType_Type"=>$Type1_Pure{"Type"});
14808 }
14809 else
14810 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014811 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014812 { # format change
14813 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14814 "Old_Value"=>$Type1{"Name"},
14815 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014816 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14817 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014818 "InitialType_Type"=>$Type1_Pure{"Type"});
14819 }
14820 elsif(tNameLock($Type1_Id, $Type2_Id))
14821 { # FIXME: correct this condition
14822 %{$LocalProblems{$Prefix."_Type"}}=(
14823 "Old_Value"=>$Type1{"Name"},
14824 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014825 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14826 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014827 "InitialType_Type"=>$Type1_Pure{"Type"});
14828 }
14829 }
14830 }
14831 }
14832 }
14833 if($Type1_PLevel!=$Type2_PLevel)
14834 {
14835 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14836 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14837 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014838 if($Level eq "Source")
14839 {
14840 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014841 "Old_Value"=>$Type1_PLevel,
14842 "New_Value"=>$Type2_PLevel);
14843 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014844 else
14845 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014846 if($Type2_PLevel>$Type1_PLevel)
14847 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014848 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14849 "Old_Value"=>$Type1_PLevel,
14850 "New_Value"=>$Type2_PLevel);
14851 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014852 else
14853 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014854 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14855 "Old_Value"=>$Type1_PLevel,
14856 "New_Value"=>$Type2_PLevel);
14857 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014858 }
14859 }
14860 }
14861 if($Type1_Pure{"Type"} eq "Array")
14862 { # base_type[N] -> base_type[N]
14863 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014864 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014865 foreach my $SubProblemType (keys(%SubProblems))
14866 {
14867 $SubProblemType=~s/_Type/_BaseType/g;
14868 next if(defined $LocalProblems{$SubProblemType});
14869 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14870 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14871 }
14872 }
14873 }
14874 return %LocalProblems;
14875}
14876
14877sub tNameLock($$)
14878{
14879 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014880 my $Changed = 0;
14881 if(differentDumps("G"))
14882 { # different GCC versions
14883 $Changed = 1;
14884 }
14885 elsif(differentDumps("V"))
14886 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014887 if(not checkDump(1, "2.20")
14888 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014889 { # latest names update
14890 # 2.6: added restrict qualifier
14891 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014892 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014893 $Changed = 1;
14894 }
14895 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014896
14897 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14898 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14899
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014900 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014901 { # different formats
14902 if($UseOldDumps)
14903 { # old dumps
14904 return 0;
14905 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014906
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014907 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14908 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014909
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014910 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014911 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014912 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014913 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014914 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014915 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014916 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014917 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014918 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14919 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14920 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014921 { # equal base types
14922 return 0;
14923 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014924
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014925 if(not checkDump(1, "2.13")
14926 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014927 { # broken array names in ABI dumps < 2.13
14928 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014929 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014930 return 0;
14931 }
14932 }
14933
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014934 if(not checkDump(1, "2.6")
14935 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014936 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014937 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014938 and $TN2=~/\brestrict\b/) {
14939 return 0;
14940 }
14941 }
14942
14943 if(not checkDump(1, "2.20")
14944 or not checkDump(2, "2.20"))
14945 { # added restrict attribute in 2.6
14946 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14947 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014948 return 0;
14949 }
14950 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014951 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014952 else
14953 {
14954 # typedef struct {...} type_t
14955 # typedef struct type_t {...} type_t
14956 if(index($TN1, " ".$TN2)!=-1)
14957 {
14958 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
14959 return 0;
14960 }
14961 }
14962 if(index($TN2, " ".$TN1)!=-1)
14963 {
14964 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
14965 return 0;
14966 }
14967 }
14968 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014969 return 1;
14970}
14971
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014972sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014973{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014974 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014975 if(defined $Cache{"differentDumps"}{$Check}) {
14976 return $Cache{"differentDumps"}{$Check};
14977 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014978 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014979 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014980 if($Check eq "G")
14981 {
14982 if(getGccVersion(1) ne getGccVersion(2))
14983 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014984 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014985 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014986 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014987 if($Check eq "V")
14988 {
14989 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
14990 formatVersion($UsedDump{2}{"V"}, 2))!=0)
14991 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014992 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014993 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014994 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014995 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014996 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014997}
14998
14999sub formatVersion($$)
15000{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015001 my ($V, $Digits) = @_;
15002 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015003 return join(".", splice(@Elems, 0, $Digits));
15004}
15005
15006sub htmlSpecChars($)
15007{
15008 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015009 if(not $Str) {
15010 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015011 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015012 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15013 $Str=~s/</&lt;/g;
15014 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15015 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015016 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15017 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015018 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015019 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015020 $Str=~s/\n/<br\/>/g;
15021 $Str=~s/\"/&quot;/g;
15022 $Str=~s/\'/&#39;/g;
15023 return $Str;
15024}
15025
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015026sub xmlSpecChars($)
15027{
15028 my $Str = $_[0];
15029 if(not $Str) {
15030 return $Str;
15031 }
15032
15033 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15034 $Str=~s/</&lt;/g;
15035 $Str=~s/>/&gt;/g;
15036
15037 $Str=~s/\"/&quot;/g;
15038 $Str=~s/\'/&#39;/g;
15039
15040 return $Str;
15041}
15042
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015043sub xmlSpecChars_R($)
15044{
15045 my $Str = $_[0];
15046 if(not $Str) {
15047 return $Str;
15048 }
15049
15050 $Str=~s/&amp;/&/g;
15051 $Str=~s/&lt;/</g;
15052 $Str=~s/&gt;/>/g;
15053
15054 $Str=~s/&quot;/"/g;
15055 $Str=~s/&#39;/'/g;
15056
15057 return $Str;
15058}
15059
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015060sub black_name($)
15061{
15062 my $Name = $_[0];
15063 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15064}
15065
15066sub highLight_Signature($)
15067{
15068 my $Signature = $_[0];
15069 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15070}
15071
15072sub highLight_Signature_Italic_Color($)
15073{
15074 my $Signature = $_[0];
15075 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15076}
15077
15078sub separate_symbol($)
15079{
15080 my $Symbol = $_[0];
15081 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15082 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15083 ($Name, $Spec, $Ver) = ($1, $2, $3);
15084 }
15085 return ($Name, $Spec, $Ver);
15086}
15087
15088sub cut_f_attrs($)
15089{
15090 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15091 return $2;
15092 }
15093 return "";
15094}
15095
15096sub highLight_Signature_PPos_Italic($$$$$)
15097{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015098 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15099 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015100 if($CheckObjectsOnly) {
15101 $ItalicParams=$ColorParams=0;
15102 }
15103 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15104 my $Return = "";
15105 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15106 $Return = $2;
15107 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015108 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015109 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015110 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015111 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015112 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015113 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015114 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015115 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015116 }
15117 return $Signature;
15118 }
15119 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15120 $Begin.=" " if($Begin!~/ \Z/);
15121 $End = cut_f_attrs($Signature);
15122 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015123 my ($Short, $Params) = split_Signature($Signature);
15124 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015125 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015126 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015127 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015128 $Part=~s/\A\s+|\s+\Z//g;
15129 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15130 if($Part=~/\([\*]+(\w+)\)/i) {
15131 $ParamName = $1;#func-ptr
15132 }
15133 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15134 $ParamName = $1;
15135 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015136 if(not $ParamName)
15137 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015138 push(@Parts, $Part_Styled);
15139 next;
15140 }
15141 if($ItalicParams and not $TName_Tid{1}{$Part}
15142 and not $TName_Tid{2}{$Part})
15143 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015144 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015145 if($Param_Pos ne ""
15146 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015147 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015148 }
15149 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015150 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015151 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015152 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015153 }
15154 $Part_Styled=~s/,(\w)/, $1/g;
15155 push(@Parts, $Part_Styled);
15156 }
15157 if(@Parts)
15158 {
15159 foreach my $Num (0 .. $#Parts)
15160 {
15161 if($Num==$#Parts)
15162 { # add ")" to the last parameter
15163 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15164 }
15165 elsif(length($Parts[$Num])<=45) {
15166 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15167 }
15168 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015169 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015170 }
15171 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015172 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015173 }
15174 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015175 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015176 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015177 $Signature=~s!\[\]![&#160;]!g;
15178 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015179 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15180 if($SymbolVersion) {
15181 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15182 }
15183 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015184}
15185
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015186sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015187{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015188 my $Signature = $_[0];
15189 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15190 {
15191 $Signature=~s/\A\Q$ShortName\E\(//g;
15192 cut_f_attrs($Signature);
15193 $Signature=~s/\)\Z//;
15194 return ($ShortName, $Signature);
15195 }
15196
15197 # error
15198 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015199}
15200
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015201sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015202{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015203 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015204 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015205 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15206 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015207 foreach my $Pos (0 .. length($Params) - 1)
15208 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015209 my $S = substr($Params, $Pos, 1);
15210 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015211 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015212 }
15213 if($S eq "," and
15214 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015215 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015216 if($Comma)
15217 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015218 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015219 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015220 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015221 }
15222 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015223 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015224 }
15225 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015226 if(not $Sp)
15227 { # remove spaces
15228 foreach (@Parts)
15229 {
15230 s/\A //g;
15231 s/ \Z//g;
15232 }
15233 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015234 return @Parts;
15235}
15236
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015237sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015238{
15239 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015240 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015241 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015242 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15243 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015244 $Center+=length($1);
15245 }
15246 foreach my $Pos (0 .. length($Sign)-1)
15247 {
15248 my $S = substr($Sign, $Pos, 1);
15249 if($S eq $Target)
15250 {
15251 if($B{"("}==$B{")"}
15252 and $B{"<"}==$B{">"}) {
15253 return $Center;
15254 }
15255 }
15256 if(defined $B{$S}) {
15257 $B{$S}+=1;
15258 }
15259 $Center+=1;
15260 }
15261 return 0;
15262}
15263
15264sub appendFile($$)
15265{
15266 my ($Path, $Content) = @_;
15267 return if(not $Path);
15268 if(my $Dir = get_dirname($Path)) {
15269 mkpath($Dir);
15270 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015271 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015272 print FILE $Content;
15273 close(FILE);
15274}
15275
15276sub writeFile($$)
15277{
15278 my ($Path, $Content) = @_;
15279 return if(not $Path);
15280 if(my $Dir = get_dirname($Path)) {
15281 mkpath($Dir);
15282 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015283 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015284 print FILE $Content;
15285 close(FILE);
15286}
15287
15288sub readFile($)
15289{
15290 my $Path = $_[0];
15291 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015292 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015293 local $/ = undef;
15294 my $Content = <FILE>;
15295 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015296 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015297 $Content=~s/\r/\n/g;
15298 }
15299 return $Content;
15300}
15301
15302sub get_filename($)
15303{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015304 if(defined $Cache{"get_filename"}{$_[0]}) {
15305 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015306 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015307 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15308 return ($Cache{"get_filename"}{$_[0]}=$1);
15309 }
15310 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015311}
15312
15313sub get_dirname($)
15314{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015315 if(defined $Cache{"get_dirname"}{$_[0]}) {
15316 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015317 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015318 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15319 return ($Cache{"get_dirname"}{$_[0]}=$1);
15320 }
15321 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015322}
15323
15324sub separate_path($) {
15325 return (get_dirname($_[0]), get_filename($_[0]));
15326}
15327
15328sub esc($)
15329{
15330 my $Str = $_[0];
15331 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15332 return $Str;
15333}
15334
15335sub readLineNum($$)
15336{
15337 my ($Path, $Num) = @_;
15338 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015339 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015340 foreach (1 ... $Num) {
15341 <FILE>;
15342 }
15343 my $Line = <FILE>;
15344 close(FILE);
15345 return $Line;
15346}
15347
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015348sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015349{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015350 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015351 return () if(not $Path or not -f $Path);
15352 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015353 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15354 {
15355 foreach my $AttrVal (split(/;/, $1))
15356 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015357 if($AttrVal=~/(.+):(.+)/)
15358 {
15359 my ($Name, $Value) = ($1, $2);
15360 $Attributes{$Name} = $Value;
15361 }
15362 }
15363 }
15364 return \%Attributes;
15365}
15366
15367sub is_abs($) {
15368 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15369}
15370
15371sub get_abs_path($)
15372{ # abs_path() should NOT be called for absolute inputs
15373 # because it can change them
15374 my $Path = $_[0];
15375 if(not is_abs($Path)) {
15376 $Path = abs_path($Path);
15377 }
15378 return $Path;
15379}
15380
15381sub get_OSgroup()
15382{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015383 my $N = $Config{"osname"};
15384 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015385 return "macos";
15386 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015387 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015388 return "bsd";
15389 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015390 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015391 return "beos";
15392 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015393 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015394 return "symbian";
15395 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015396 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015397 return "windows";
15398 }
15399 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015400 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015401 }
15402}
15403
15404sub getGccVersion($)
15405{
15406 my $LibVersion = $_[0];
15407 if($GCC_VERSION{$LibVersion})
15408 { # dump version
15409 return $GCC_VERSION{$LibVersion};
15410 }
15411 elsif($UsedDump{$LibVersion}{"V"})
15412 { # old-version dumps
15413 return "unknown";
15414 }
15415 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15416 if(not $GccVersion) {
15417 return "unknown";
15418 }
15419 return $GccVersion;
15420}
15421
15422sub showArch($)
15423{
15424 my $Arch = $_[0];
15425 if($Arch eq "arm"
15426 or $Arch eq "mips") {
15427 return uc($Arch);
15428 }
15429 return $Arch;
15430}
15431
15432sub getArch($)
15433{
15434 my $LibVersion = $_[0];
15435 if($CPU_ARCH{$LibVersion})
15436 { # dump version
15437 return $CPU_ARCH{$LibVersion};
15438 }
15439 elsif($UsedDump{$LibVersion}{"V"})
15440 { # old-version dumps
15441 return "unknown";
15442 }
15443 if(defined $Cache{"getArch"}{$LibVersion}) {
15444 return $Cache{"getArch"}{$LibVersion};
15445 }
15446 my $Arch = get_dumpmachine($GCC_PATH); # host version
15447 if(not $Arch) {
15448 return "unknown";
15449 }
15450 if($Arch=~/\A([\w]{3,})(-|\Z)/) {
15451 $Arch = $1;
15452 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040015453 $Arch = "x86" if($Arch=~/\Ai[3-7]86\Z/i);
15454 $Arch = "x86_64" if($Arch=~/\Aamd64\Z/i);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040015455 if($OSgroup eq "windows")
15456 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015457 $Arch = "x86" if($Arch=~/win32|mingw32/i);
15458 $Arch = "x86_64" if($Arch=~/win64|mingw64/i);
15459 }
15460 $Cache{"getArch"}{$LibVersion} = $Arch;
15461 return $Arch;
15462}
15463
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015464sub get_Report_Header($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015465{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015466 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015467 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015468 if(getArch(1) ne getArch(2)
15469 or getArch(1) eq "unknown"
15470 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015471 { # don't show architecture in the header
15472 $ArchInfo="";
15473 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015474 my $Report_Header = "<h1><span class='nowrap'>";
15475 if($Level eq "Source") {
15476 $Report_Header .= "Source compatibility";
15477 }
15478 elsif($Level eq "Binary") {
15479 $Report_Header .= "Binary compatibility";
15480 }
15481 else {
15482 $Report_Header .= "API compatibility";
15483 }
15484 $Report_Header .= " report for the <span style='color:Blue;'>$TargetLibraryFName</span> $TargetComponent</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015485 $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>";
15486 if($AppPath) {
15487 $Report_Header .= " <span class='nowrap'>&#160;(relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)</span>";
15488 }
15489 $Report_Header .= "</h1>\n";
15490 return $Report_Header;
15491}
15492
15493sub get_SourceInfo()
15494{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015495 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015496 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015497 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015498 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015499 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015500 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15501 $CheckedHeaders .= "<div class='h_list'>\n";
15502 foreach my $Header_Path (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15503 {
15504 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15505 my $Name = get_filename($Identity);
15506 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15507 $CheckedHeaders .= $Name.$Comment."<br/>\n";
15508 }
15509 $CheckedHeaders .= "</div>\n";
15510 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015511 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015512
15513 if(my @Sources = keys(%{$Registered_Sources{1}}))
15514 {
15515 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15516 $CheckedSources .= "<div class='h_list'>\n";
15517 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15518 {
15519 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15520 my $Name = get_filename($Identity);
15521 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15522 $CheckedSources .= $Name.$Comment."<br/>\n";
15523 }
15524 $CheckedSources .= "</div>\n";
15525 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15526 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015527 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015528 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015529 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015530 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015531 $CheckedLibs .= "<div class='lib_list'>\n";
15532 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15533 {
15534 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15535 $CheckedLibs .= $Library."<br/>\n";
15536 }
15537 $CheckedLibs .= "</div>\n";
15538 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015539 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015540 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15541}
15542
15543sub get_ObjTitle()
15544{
15545 if(defined $UsedDump{1}{"DWARF"}) {
15546 return "Objects";
15547 }
15548 else {
15549 return ucfirst($SLIB_TYPE)." Libraries";
15550 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015551}
15552
15553sub get_TypeProblems_Count($$$)
15554{
15555 my ($TypeChanges, $TargetPriority, $Level) = @_;
15556 my $Type_Problems_Count = 0;
15557 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15558 {
15559 my %Kinds_Target = ();
15560 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15561 {
15562 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15563 {
15564 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
15565 my $Priority = getProblemSeverity($Level, $Kind);
15566 next if($Priority ne $TargetPriority);
15567 if($Kinds_Target{$Kind}{$Target}) {
15568 next;
15569 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015570 if(cmpSeverities($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015571 { # select a problem with the highest priority
15572 next;
15573 }
15574 $Kinds_Target{$Kind}{$Target} = 1;
15575 $Type_Problems_Count += 1;
15576 }
15577 }
15578 }
15579 return $Type_Problems_Count;
15580}
15581
15582sub get_Summary($)
15583{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015584 my $Level = $_[0];
15585 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015586 $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 +040015587 %{$RESULT{$Level}} = (
15588 "Problems"=>0,
15589 "Warnings"=>0,
15590 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015591 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015592 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015593 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015594 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015595 {
15596 if(not defined $CompatRules{$Level}{$Kind})
15597 { # unknown rule
15598 if(not $UnknownRules{$Level}{$Kind})
15599 { # only one warning
15600 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15601 $UnknownRules{$Level}{$Kind}=1;
15602 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015603 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015604 }
15605 }
15606 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015607 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15608 {
15609 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15610 {
15611 if(not defined $CompatRules{$Level}{$Kind})
15612 { # unknown rule
15613 if(not $UnknownRules{$Level}{$Kind})
15614 { # only one warning
15615 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15616 $UnknownRules{$Level}{$Kind}=1;
15617 }
15618 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15619 }
15620 }
15621 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015622 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015623 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015624 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015625 {
15626 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15627 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015628 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015629 {
15630 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015631 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015632 $Added += 1;
15633 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015634 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015635 {
15636 $Removed += 1;
15637 $TotalAffected{$Level}{$Interface} = $Priority;
15638 }
15639 else
15640 {
15641 if($Priority eq "Safe") {
15642 $I_Other += 1;
15643 }
15644 elsif($Priority eq "High") {
15645 $I_Problems_High += 1;
15646 }
15647 elsif($Priority eq "Medium") {
15648 $I_Problems_Medium += 1;
15649 }
15650 elsif($Priority eq "Low") {
15651 $I_Problems_Low += 1;
15652 }
15653 if(($Priority ne "Low" or $StrictCompat)
15654 and $Priority ne "Safe") {
15655 $TotalAffected{$Level}{$Interface} = $Priority;
15656 }
15657 }
15658 }
15659 }
15660 }
15661 }
15662 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015663 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015664 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015665 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015666 {
15667 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15668 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015669 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015670 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015671 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15672 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015673 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015674 if(cmpSeverities($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015675 { # select a problem with the highest priority
15676 next;
15677 }
15678 if(($Priority ne "Low" or $StrictCompat)
15679 and $Priority ne "Safe") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015680 $TotalAffected{$Level}{$Interface} = maxSeverity($TotalAffected{$Level}{$Interface}, $Priority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015681 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015682 %{$TypeChanges{$Type_Name}{$Kind}{$Location}} = %{$CompatProblems{$Level}{$Interface}{$Kind}{$Location}};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015683 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = maxSeverity($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015684 }
15685 }
15686 }
15687 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015688
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015689 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15690 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15691 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15692 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015693
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015694 if($CheckObjectsOnly)
15695 { # only removed exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015696 $RESULT{$Level}{"Affected"} = $Removed*100/keys(%{$Symbol_Library{1}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015697 }
15698 else
15699 { # changed and removed public symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015700 my $SCount = keys(%{$CheckedSymbols{$Level}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015701 if($ExtendedCheck)
15702 { # don't count external_func_0 for constants
15703 $SCount-=1;
15704 }
15705 if($SCount)
15706 {
15707 my %Weight = (
15708 "High" => 100,
15709 "Medium" => 50,
15710 "Low" => 25
15711 );
15712 foreach (keys(%{$TotalAffected{$Level}})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015713 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015714 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015715 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015716 }
15717 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015718 $RESULT{$Level}{"Affected"} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015719 }
15720 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015721 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15722 if($RESULT{$Level}{"Affected"}>=100) {
15723 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015724 }
15725
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015726 $RESULT{$Level}{"Problems"} += $Removed;
15727 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015728 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015729 if($StrictCompat) {
15730 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15731 }
15732 else {
15733 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15734 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015735
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015736 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015737 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015738 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015739 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015740 my $Severity = getProblemSeverity($Level, $Kind);
15741 if($Severity eq "Safe")
15742 {
15743 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015744 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015745 elsif($Severity eq "Low")
15746 {
15747 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015748 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015749 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015750 }
15751
15752 if($C_Problems_Low)
15753 {
15754 if($StrictCompat) {
15755 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15756 }
15757 else {
15758 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015759 }
15760 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015761 if($CheckImpl and $Level eq "Binary")
15762 {
15763 if($StrictCompat) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015764 $RESULT{$Level}{"Problems"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015765 }
15766 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015767 $RESULT{$Level}{"Warnings"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015768 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015769 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015770 if($RESULT{$Level}{"Problems"}
15771 and $RESULT{$Level}{"Affected"}) {
15772 $RESULT{$Level}{"Verdict"} = "incompatible";
15773 }
15774 else {
15775 $RESULT{$Level}{"Verdict"} = "compatible";
15776 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015777
15778 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15779 if(not $TotalTypes)
15780 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015781 $TotalTypes = keys(%{$TName_Tid{1}});
15782 }
15783
15784 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15785 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15786
15787 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15788
15789 if($ReportFormat eq "xml")
15790 { # XML
15791 # test info
15792 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15793 $TestInfo .= " <version1>\n";
15794 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
15795 $TestInfo .= " <architecture>$Arch1</architecture>\n";
15796 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15797 $TestInfo .= " </version1>\n";
15798
15799 $TestInfo .= " <version2>\n";
15800 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
15801 $TestInfo .= " <architecture>$Arch2</architecture>\n";
15802 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15803 $TestInfo .= " </version2>\n";
15804 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15805
15806 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015807 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015808 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015809 $TestResults .= " <headers>\n";
15810 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15811 {
15812 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15813 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15814 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15815 }
15816 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015817 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015818
15819 if(my @Sources = keys(%{$Registered_Sources{1}}))
15820 {
15821 $TestResults .= " <sources>\n";
15822 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15823 {
15824 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15825 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15826 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15827 }
15828 $TestResults .= " </sources>\n";
15829 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015830
15831 $TestResults .= " <libs>\n";
15832 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15833 {
15834 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15835 $TestResults .= " <name>$Library</name>\n";
15836 }
15837 $TestResults .= " </libs>\n";
15838
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015839 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015840 $TestResults .= " <types>".$TotalTypes."</types>\n";
15841
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015842 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15843 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015844 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15845
15846 # problem summary
15847 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15848 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15849
15850 $Problem_Summary .= " <problems_with_types>\n";
15851 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15852 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15853 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15854 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15855 $Problem_Summary .= " </problems_with_types>\n";
15856
15857 $Problem_Summary .= " <problems_with_symbols>\n";
15858 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15859 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15860 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015861 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015862 $Problem_Summary .= " </problems_with_symbols>\n";
15863
15864 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015865 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015866 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015867 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015868 {
15869 $Problem_Summary .= " <impl>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015870 $Problem_Summary .= " <low>".keys(%CompatProblems_Impl)."</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015871 $Problem_Summary .= " </impl>\n";
15872 }
15873 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15874
15875 return ($TestInfo.$TestResults.$Problem_Summary, "");
15876 }
15877 else
15878 { # HTML
15879 # test info
15880 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015881 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015882 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetLibraryFName</td></tr>\n";
15883
15884 my (@VInf1, @VInf2, $AddTestInfo) = ();
15885 if($Arch1 ne "unknown"
15886 and $Arch2 ne "unknown")
15887 { # CPU arch
15888 if($Arch1 eq $Arch2)
15889 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015890 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015891 }
15892 else
15893 { # go to the version number
15894 push(@VInf1, showArch($Arch1));
15895 push(@VInf2, showArch($Arch2));
15896 }
15897 }
15898 if($GccV1 ne "unknown"
15899 and $GccV2 ne "unknown"
15900 and $OStarget ne "windows")
15901 { # GCC version
15902 if($GccV1 eq $GccV2)
15903 { # go to the separate section
15904 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15905 }
15906 else
15907 { # go to the version number
15908 push(@VInf1, "gcc ".$GccV1);
15909 push(@VInf2, "gcc ".$GccV2);
15910 }
15911 }
15912 # show long version names with GCC version and CPU architecture name (if different)
15913 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
15914 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
15915 $TestInfo .= $AddTestInfo;
15916 #if($COMMON_LANGUAGE{1}) {
15917 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
15918 #}
15919 if($ExtendedCheck) {
15920 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
15921 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015922 if($JoinReport)
15923 {
15924 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015925 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015926 }
15927 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015928 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015929 }
15930 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015931 $TestInfo .= "</table>\n";
15932
15933 # test results
15934 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015935 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015936
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015937 if(my @Headers = keys(%{$Registered_Headers{1}}))
15938 {
15939 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
15940 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
15941 }
15942 elsif($CheckObjectsOnly) {
15943 $TestResults .= "<tr><th>Total Header Files</th><td>0&#160;(not&#160;analyzed)</td></tr>\n";
15944 }
15945
15946 if(my @Sources = keys(%{$Registered_Sources{1}}))
15947 {
15948 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
15949 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
15950 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015951
15952 if(not $ExtendedCheck)
15953 {
15954 my $Libs_Link = "0";
15955 $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 +040015956 $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 +040015957 }
15958
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015959 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015960
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015961 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015962 if($JoinReport) {
15963 $META_DATA = "kind:".lc($Level).";".$META_DATA;
15964 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015965 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015966 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015967 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
15968 }
15969 else {
15970 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
15971 }
15972 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015973 $TestResults .= "</table>\n";
15974
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015975 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015976 # problem summary
15977 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015978 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015979 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
15980
15981 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015982 if($Added>0)
15983 {
15984 if($JoinReport) {
15985 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
15986 }
15987 else {
15988 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
15989 }
15990 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015991 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015992 $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 +040015993
15994 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015995 if($Removed>0)
15996 {
15997 if($JoinReport) {
15998 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
15999 }
16000 else {
16001 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16002 }
16003 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016004 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016005 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
16006 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016007
16008 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016009 $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 +040016010 $TH_Link = "n/a" if($CheckObjectsOnly);
16011 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016012 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
16013 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016014
16015 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016016 $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 +040016017 $TM_Link = "n/a" if($CheckObjectsOnly);
16018 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016019 $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 +040016020
16021 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016022 $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 +040016023 $TL_Link = "n/a" if($CheckObjectsOnly);
16024 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016025 $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 +040016026
16027 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016028 $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 +040016029 $IH_Link = "n/a" if($CheckObjectsOnly);
16030 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016031 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
16032 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016033
16034 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016035 $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 +040016036 $IM_Link = "n/a" if($CheckObjectsOnly);
16037 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016038 $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 +040016039
16040 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016041 $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 +040016042 $IL_Link = "n/a" if($CheckObjectsOnly);
16043 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016044 $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 +040016045
16046 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016047 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16048 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016049 }
16050 $ChangedConstants_Link = "n/a" if($CheckObjectsOnly);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016051 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016052 $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 +040016053
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016054 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016055 {
16056 my $ChangedImpl_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016057 $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 +040016058 $ChangedImpl_Link = "n/a" if($CheckHeadersOnly);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016059 $META_DATA .= "changed_implementation:".keys(%CompatProblems_Impl).";";
16060 $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 +040016061 }
16062 # Safe Changes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016063 if($T_Other and not $CheckObjectsOnly)
16064 {
16065 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016066 $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 +040016067 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016068
16069 if($I_Other and not $CheckObjectsOnly)
16070 {
16071 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016072 $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 +040016073 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016074
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016075 if($C_Other and not $CheckObjectsOnly)
16076 {
16077 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
16078 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
16079 }
16080
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016081 $META_DATA .= "tool_version:$TOOL_VERSION";
16082 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016083 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016084 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16085 }
16086}
16087
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016088sub getStyle($$$)
16089{
16090 my ($Subj, $Act, $Num) = @_;
16091 my %Style = (
16092 "A"=>"new",
16093 "R"=>"failed",
16094 "S"=>"passed",
16095 "L"=>"warning",
16096 "M"=>"failed",
16097 "H"=>"failed"
16098 );
16099 if($Num>0) {
16100 return " class='".$Style{$Act}."'";
16101 }
16102 return "";
16103}
16104
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016105sub show_number($)
16106{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016107 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016108 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016109 my $Num = cut_off_number($_[0], 2, 0);
16110 if($Num eq "0")
16111 {
16112 foreach my $P (3 .. 7)
16113 {
16114 $Num = cut_off_number($_[0], $P, 1);
16115 if($Num ne "0") {
16116 last;
16117 }
16118 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016119 }
16120 if($Num eq "0") {
16121 $Num = $_[0];
16122 }
16123 return $Num;
16124 }
16125 return $_[0];
16126}
16127
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016128sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016129{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016130 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016131 if($num!~/\./)
16132 {
16133 $num .= ".";
16134 foreach (1 .. $digs_to_cut-1) {
16135 $num .= "0";
16136 }
16137 }
16138 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16139 {
16140 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16141 $num .= "0";
16142 }
16143 }
16144 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16145 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16146 }
16147 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016148 if($z) {
16149 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16150 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016151 return $num;
16152}
16153
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016154sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016155{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016156 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016157 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016158
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016159 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016160 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16161 {
16162 my $Header = $Constants{1}{$Constant}{"Header"};
16163 if(not $Header)
16164 { # added
16165 $Header = $Constants{2}{$Constant}{"Header"}
16166 }
16167
16168 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16169 {
16170 if(not defined $CompatRules{$Level}{$Kind}) {
16171 next;
16172 }
16173 if($TargetSeverity ne getProblemSeverity($Level, $Kind)) {
16174 next;
16175 }
16176 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16177 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016178 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016179
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016180 if($ReportFormat eq "xml")
16181 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016182 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016183 {
16184 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016185 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016186 {
16187 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016188 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16189 {
16190 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16191 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16192 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016193
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016194 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16195 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16196 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
16197 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16198 $CHANGED_CONSTANTS .= " </problem>\n";
16199 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016200 $CHANGED_CONSTANTS .= " </constant>\n";
16201 }
16202 $CHANGED_CONSTANTS .= " </header>\n";
16203 }
16204 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16205 }
16206 else
16207 { # HTML
16208 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016209 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016210 {
16211 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016212 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016213 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016214 my $Report = "";
16215
16216 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16217 {
16218 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16219 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16220 $Report .= "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16221 $Number += 1;
16222 }
16223 if($Report)
16224 {
16225 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n";
16226 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16227 $Report = insertIDs($Report);
16228 }
16229 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016230 }
16231 $CHANGED_CONSTANTS .= "<br/>\n";
16232 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016233 if($CHANGED_CONSTANTS)
16234 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016235 my $Title = "Problems with Constants, $TargetSeverity Severity";
16236 if($TargetSeverity eq "Safe")
16237 { # Safe Changes
16238 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016239 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016240 $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 +040016241 }
16242 }
16243 return $CHANGED_CONSTANTS;
16244}
16245
16246sub get_Report_Impl()
16247{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016248 my $CHANGED_IMPLEMENTATION = "";
16249 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016250 foreach my $Interface (sort keys(%CompatProblems_Impl))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016251 {
16252 my $HeaderName = $CompleteSignature{1}{$Interface}{"Header"};
16253 my $DyLib = $Symbol_Library{1}{$Interface};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016254 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016255 }
16256 my $Changed_Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016257 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016258 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016259 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016260 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016261 my %NameSpaceSymbols = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016262 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016263 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016264 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016265 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016266 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016267 $CHANGED_IMPLEMENTATION .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016268 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016269 foreach my $Interface (@SortedInterfaces)
16270 {
16271 $Changed_Number += 1;
16272 my $Signature = get_Signature($Interface, 1);
16273 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016274 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016275 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016276 $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 +040016277 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016278 $CHANGED_IMPLEMENTATION .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016279 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016280 }
16281 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016282 if($CHANGED_IMPLEMENTATION)
16283 {
16284 $CHANGED_IMPLEMENTATION = insertIDs($CHANGED_IMPLEMENTATION);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016285 $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 +040016286 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016287
16288 # clean memory
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016289 %CompatProblems_Impl = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016290
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016291 return $CHANGED_IMPLEMENTATION;
16292}
16293
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016294sub getTitle($$$)
16295{
16296 my ($Header, $Library, $NameSpace) = @_;
16297 my $Title = "";
16298 if($Library and $Library!~/\.\w+\Z/) {
16299 $Library .= " (.$LIB_EXT)";
16300 }
16301 if($Header and $Library)
16302 {
16303 $Title .= "<span class='h_name'>$Header</span>";
16304 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16305 }
16306 elsif($Library) {
16307 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16308 }
16309 elsif($Header) {
16310 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16311 }
16312 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016313 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016314 }
16315 return $Title;
16316}
16317
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016318sub get_Report_Added($)
16319{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016320 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016321 my $ADDED_INTERFACES = "";
16322 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016323 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016324 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016325 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016326 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016327 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016328 {
16329 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16330 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016331 if($Level eq "Source" and $ReportFormat eq "html")
16332 { # do not show library name in HTML report
16333 $DyLib = "";
16334 }
16335 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016336 }
16337 }
16338 }
16339 if($ReportFormat eq "xml")
16340 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016341 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016342 {
16343 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016344 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016345 {
16346 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016347 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016348 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16349 }
16350 $ADDED_INTERFACES .= " </library>\n";
16351 }
16352 $ADDED_INTERFACES .= " </header>\n";
16353 }
16354 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16355 }
16356 else
16357 { # HTML
16358 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016359 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016360 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016361 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016362 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016363 my %NameSpaceSymbols = ();
16364 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016365 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016366 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016367 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016368 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016369 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16370 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016371 foreach my $Interface (@SortedInterfaces)
16372 {
16373 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016374 my $Signature = get_Signature($Interface, 2);
16375 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016376 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016377 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016378 if($Interface=~/\A(_Z|\?)/)
16379 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016380 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016381 $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 +040016382 }
16383 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016384 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016385 }
16386 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016387 else
16388 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016389 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016390 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016391 }
16392 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016393 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016394 }
16395 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016396 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016397 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016398 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016399 }
16400 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016401 if($ADDED_INTERFACES)
16402 {
16403 my $Anchor = "<a name='Added'></a>";
16404 if($JoinReport) {
16405 $Anchor = "<a name='".$Level."_Added'></a>";
16406 }
16407 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016408 }
16409 }
16410 return $ADDED_INTERFACES;
16411}
16412
16413sub get_Report_Removed($)
16414{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016415 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016416 my $REMOVED_INTERFACES = "";
16417 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016418 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016419 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016420 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016421 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016422 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016423 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016424 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16425 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016426 if($Level eq "Source" and $ReportFormat eq "html")
16427 { # do not show library name in HTML report
16428 $DyLib = "";
16429 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016430 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016431 }
16432 }
16433 }
16434 if($ReportFormat eq "xml")
16435 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016436 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016437 {
16438 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016439 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016440 {
16441 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016442 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16443 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016444 }
16445 $REMOVED_INTERFACES .= " </library>\n";
16446 }
16447 $REMOVED_INTERFACES .= " </header>\n";
16448 }
16449 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16450 }
16451 else
16452 { # HTML
16453 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016454 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016455 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016456 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016457 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016458 my %NameSpaceSymbols = ();
16459 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016460 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016461 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016462 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016463 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016464 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16465 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016466 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016467 {
16468 $Removed_Number += 1;
16469 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016470 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016471 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016472 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016473 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016474 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016475 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016476 if($Signature) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016477 $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 +040016478 }
16479 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016480 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016481 }
16482 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016483 else
16484 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016485 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016486 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016487 }
16488 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016489 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016490 }
16491 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016492 }
16493 }
16494 $REMOVED_INTERFACES .= "<br/>\n";
16495 }
16496 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016497 if($REMOVED_INTERFACES)
16498 {
16499 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16500 if($JoinReport) {
16501 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16502 }
16503 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016504 }
16505 }
16506 return $REMOVED_INTERFACES;
16507}
16508
16509sub getXmlParams($$)
16510{
16511 my ($Content, $Problem) = @_;
16512 return "" if(not $Content or not $Problem);
16513 my %XMLparams = ();
16514 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16515 {
16516 my $Macro = "\@".lc($Attr);
16517 if($Content=~/\Q$Macro\E/) {
16518 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16519 }
16520 }
16521 my @PString = ();
16522 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016523 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016524 }
16525 if(@PString) {
16526 return " ".join(" ", @PString);
16527 }
16528 else {
16529 return "";
16530 }
16531}
16532
16533sub addMarkup($)
16534{
16535 my $Content = $_[0];
16536 # auto-markup
16537 $Content=~s/\n[ ]*//; # spaces
16538 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16539 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016540 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016541 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16542 if($Content=~/\ANOTE:/)
16543 { # notes
16544 $Content=~s!(NOTE):!<b>$1</b>:!g;
16545 }
16546 else {
16547 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16548 }
16549 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16550 my @Keywords = (
16551 "void",
16552 "const",
16553 "static",
16554 "restrict",
16555 "volatile",
16556 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016557 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016558 );
16559 my $MKeys = join("|", @Keywords);
16560 foreach (@Keywords) {
16561 $MKeys .= "|non-".$_;
16562 }
16563 $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 +040016564
16565 # Markdown
16566 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16567 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016568 return $Content;
16569}
16570
16571sub applyMacroses($$$$)
16572{
16573 my ($Level, $Kind, $Content, $Problem) = @_;
16574 return "" if(not $Content or not $Problem);
16575 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16576 $Content = addMarkup($Content);
16577 # macros
16578 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16579 {
16580 my $Macro = "\@".lc($Attr);
16581 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016582 if(not defined $Value
16583 or $Value eq "") {
16584 next;
16585 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016586 if($Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016587 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016588 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
16589 $Value=~s/\s\w+(\)|,)/$1/g; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016590 $Value = black_name($Value);
16591 }
16592 elsif($Value=~/\s/) {
16593 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16594 }
16595 elsif($Value=~/\A\d+\Z/
16596 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16597 { # bits to bytes
16598 if($Value % $BYTE_SIZE)
16599 { # bits
16600 if($Value==1) {
16601 $Value = "<b>".$Value."</b> bit";
16602 }
16603 else {
16604 $Value = "<b>".$Value."</b> bits";
16605 }
16606 }
16607 else
16608 { # bytes
16609 $Value /= $BYTE_SIZE;
16610 if($Value==1) {
16611 $Value = "<b>".$Value."</b> byte";
16612 }
16613 else {
16614 $Value = "<b>".$Value."</b> bytes";
16615 }
16616 }
16617 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016618 else
16619 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016620 $Value = "<b>".htmlSpecChars($Value)."</b>";
16621 }
16622 $Content=~s/\Q$Macro\E/$Value/g;
16623 }
16624
16625 if($Content=~/(\A|[^\@\w])\@\w/)
16626 {
16627 if(not $IncompleteRules{$Level}{$Kind})
16628 { # only one warning
16629 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16630 $IncompleteRules{$Level}{$Kind} = 1;
16631 }
16632 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016633 return $Content;
16634}
16635
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016636sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016637{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016638 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016639 my $INTERFACE_PROBLEMS = "";
16640 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016641 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016642 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016643 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16644 if($SV and defined $CompatProblems{$Level}{$SN}) {
16645 next;
16646 }
16647 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016648 {
16649 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016650 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016651 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016652 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16653 my $DyLib = $Symbol_Library{1}{$Symbol};
16654 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016655 { # Symbol with Version
16656 $DyLib = $Symbol_Library{1}{$VSym};
16657 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016658 if(not $DyLib)
16659 { # const global data
16660 $DyLib = "";
16661 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016662 if($Level eq "Source" and $ReportFormat eq "html")
16663 { # do not show library name in HTML report
16664 $DyLib = "";
16665 }
16666 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16667 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016668 {
16669 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016670 if($Priority ne $TargetSeverity) {
16671 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016672 }
16673 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016674 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16675 {
16676 delete($SymbolChanges{$Symbol}{$Kind});
16677 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016678 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016679 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016680 }
16681 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016682 if(not keys(%{$SymbolChanges{$Symbol}})) {
16683 delete($SymbolChanges{$Symbol});
16684 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016685 }
16686 if($ReportFormat eq "xml")
16687 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016688 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016689 {
16690 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016691 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016692 {
16693 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016694 foreach my $Symbol (sort {lc($tr_name{$a}?$tr_name{$a}:$a) cmp lc($tr_name{$b}?$tr_name{$b}:$b)} keys(%SymbolChanges))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016695 {
16696 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16697 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16698 {
16699 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16700 {
16701 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016702 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016703 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16704 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16705 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16706 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16707 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
16708 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
16709 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16710 $INTERFACE_PROBLEMS .= " </problem>\n";
16711 }
16712 }
16713 $INTERFACE_PROBLEMS .= " </symbol>\n";
16714 }
16715 $INTERFACE_PROBLEMS .= " </library>\n";
16716 }
16717 $INTERFACE_PROBLEMS .= " </header>\n";
16718 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016719 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016720 }
16721 else
16722 { # HTML
16723 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016724 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016725 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016726 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016727 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016728 my (%NameSpaceSymbols, %NewSignature) = ();
16729 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016730 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016731 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016732 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016733 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016734 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016735 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 +040016736 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016737 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016738 my $Signature = get_Signature($Symbol, 1);
16739 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016740 my $ProblemNum = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016741 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016742 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016743 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016744 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016745 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016746 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016747 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016748 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016749 }
16750 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16751 {
16752 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016753 $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 +040016754 $ProblemNum += 1;
16755 $ProblemsNum += 1;
16756 }
16757 }
16758 }
16759 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016760 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016761 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016762 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016763 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016764 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016765 }
16766 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016767 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016768 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016769 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16770 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16771 if($NewSignature{$Symbol})
16772 { # argument list changed to
16773 $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 +040016774 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016775 if($Symbol=~/\A(_Z|\?)/) {
16776 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16777 }
16778 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n";
16779 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016780 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016781 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016782 }
16783 }
16784 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016785 $INTERFACE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016786 }
16787 }
16788 }
16789 if($INTERFACE_PROBLEMS)
16790 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016791 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16792 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16793 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016794 { # Safe Changes
16795 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016796 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016797 $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 +040016798 }
16799 }
16800 return $INTERFACE_PROBLEMS;
16801}
16802
16803sub get_Report_TypeProblems($$)
16804{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016805 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016806 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016807 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016808 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016809 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016810 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016811 {
16812 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16813 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016814 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016815 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016816 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016817 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016818 my $Severity = getProblemSeverity($Level, $Kind);
16819 if($Severity eq "Safe"
16820 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016821 next;
16822 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016823
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016824 if(cmpSeverities($Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target}, $Severity))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016825 { # select a problem with the highest priority
16826 next;
16827 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016828 %{$TypeChanges{$TypeName}{$Kind}{$Location}} = %{$CompatProblems{$Level}{$Interface}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016829 }
16830 }
16831 }
16832 }
16833 my %Kinds_Locations = ();
16834 foreach my $TypeName (keys(%TypeChanges))
16835 {
16836 my %Kinds_Target = ();
16837 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16838 {
16839 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
16840 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016841 my $Severity = getProblemSeverity($Level, $Kind);
16842 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016843 { # other priority
16844 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16845 next;
16846 }
16847 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16848 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
16849 if($Kinds_Target{$Kind}{$Target})
16850 { # duplicate target
16851 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16852 next;
16853 }
16854 $Kinds_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016855 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016856 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016857 }
16858 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16859 delete($TypeChanges{$TypeName}{$Kind});
16860 }
16861 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016862 if(not keys(%{$TypeChanges{$TypeName}})) {
16863 delete($TypeChanges{$TypeName});
16864 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016865 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016866 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 +040016867 if($ReportFormat eq "xml")
16868 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016869 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016870 {
16871 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016872 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016873 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016874 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016875 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16876 {
16877 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
16878 {
16879 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16880 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16881 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16882 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16883 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16884 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
16885 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
16886 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16887 $TYPE_PROBLEMS .= " </problem>\n";
16888 }
16889 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016890 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016891 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016892 $TYPE_PROBLEMS .= showVTables($TypeName);
16893 }
16894 $TYPE_PROBLEMS .= " </type>\n";
16895 }
16896 $TYPE_PROBLEMS .= " </header>\n";
16897 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016898 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016899 }
16900 else
16901 { # HTML
16902 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016903 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016904 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016905 my (%NameSpace_Type) = ();
16906 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016907 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016908 }
16909 foreach my $NameSpace (sort keys(%NameSpace_Type))
16910 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016911 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016912 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 +040016913 foreach my $TypeName (@SortedTypes)
16914 {
16915 my $ProblemNum = 1;
16916 my $TYPE_REPORT = "";
16917 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16918 {
16919 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
16920 {
16921 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16922 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16923 {
16924 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
16925 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16926 $ProblemNum += 1;
16927 $ProblemsNum += 1;
16928 }
16929 }
16930 }
16931 $ProblemNum -= 1;
16932 if($TYPE_REPORT)
16933 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016934 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016935 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016936 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016937 $ShowVTables = showVTables($TypeName);
16938 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016939
16940 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016941 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
16942 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
16943 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
16944 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016945 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016946 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016947 }
16948 }
16949 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016950 $TYPE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016951 }
16952 }
16953 if($TYPE_PROBLEMS)
16954 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016955 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
16956 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016957 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016958 { # Safe Changes
16959 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016960 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016961 $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 +040016962 }
16963 }
16964 return $TYPE_PROBLEMS;
16965}
16966
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016967sub show_Type($$$)
16968{
16969 my ($Name, $Html, $LibVersion) = @_;
16970 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
16971 $TType = lc($TType);
16972 if($TType=~/struct|union|enum/) {
16973 $Name=~s/\A\Q$TType\E //g;
16974 }
16975 if($Html) {
16976 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
16977 }
16978 else {
16979 $Name = $TType." ".$Name;
16980 }
16981 return $Name;
16982}
16983
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016984sub get_Anchor($$$)
16985{
16986 my ($Kind, $Level, $Severity) = @_;
16987 if($JoinReport)
16988 {
16989 if($Severity eq "Safe") {
16990 return "Other_".$Level."_Changes_In_".$Kind."s";
16991 }
16992 else {
16993 return $Kind."_".$Level."_Problems_".$Severity;
16994 }
16995 }
16996 else
16997 {
16998 if($Severity eq "Safe") {
16999 return "Other_Changes_In_".$Kind."s";
17000 }
17001 else {
17002 return $Kind."_Problems_".$Severity;
17003 }
17004 }
17005}
17006
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017007sub showVTables($)
17008{
17009 my $TypeName = $_[0];
17010 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017011 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017012 if(defined $Type1{"VTable"}
17013 and keys(%{$Type1{"VTable"}}))
17014 {
17015 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017016 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017017 if(defined $Type2{"VTable"}
17018 and keys(%{$Type2{"VTable"}}))
17019 {
17020 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17021 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017022 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017023 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017024 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17025 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017026 }
17027 my $VTABLES = "";
17028 if($ReportFormat eq "xml")
17029 { # XML
17030 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017031 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017032 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017033 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017034 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17035 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017036 $VTABLES .= " </entry>\n";
17037 }
17038 $VTABLES .= " </vtable>\n\n";
17039 }
17040 else
17041 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017042 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017043 $VTABLES .= "<tr><th width='2%'>Offset</th>";
17044 $VTABLES .= "<th width='45%'>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
17045 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017046 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017047 {
17048 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017049 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017050 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017051 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017052 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017053 $Color1 = " class='failed'";
17054 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017055 }
17056 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017057 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017058 }
17059 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017060 $VTABLES .= "<tr><th>".$Index."</th>\n";
17061 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17062 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017063 }
17064 $VTABLES .= "</table><br/>\n";
17065 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017066 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017067 }
17068 return $VTABLES;
17069 }
17070 }
17071 return "";
17072}
17073
17074sub simpleVEntry($)
17075{
17076 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017077 if(not defined $VEntry
17078 or $VEntry eq "") {
17079 return "";
17080 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017081 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17082 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17083 if($VEntry=~/\A_ZThn.+\Z/) {
17084 $VEntry = "non-virtual thunk";
17085 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017086 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017087 # support for old GCC versions
17088 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17089 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17090 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017091 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17092 return $VEntry;
17093}
17094
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017095sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017096{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017097 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017098 my $LIMIT = 1000;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017099 if($#{$Syms}>=10000)
17100 { # reduce size of the report
17101 $LIMIT = 10;
17102 }
17103 my %SProblems = ();
17104 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017105 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017106 if(keys(%SProblems)>$LIMIT) {
17107 last;
17108 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017109 if(($Symbol=~/C2E|D2E|D0E/))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017110 { # duplicated problems for C2 constructors, D2 and D0 destructors
17111 next;
17112 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017113 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17114 if($Level eq "Source")
17115 { # remove symbol version
17116 $Symbol=$SN;
17117 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017118 my ($MinPath_Length, $ProblemLocation_Last) = (-1, "");
17119 my $Severity_Max = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017120 my $Signature = get_Signature($Symbol, 1);
17121 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017122 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017123 foreach my $Location (keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017124 {
17125 if(not defined $Kinds_Locations->{$Kind}
17126 or not $Kinds_Locations->{$Kind}{$Location}) {
17127 next;
17128 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017129 if($SV and defined $CompatProblems{$Level}{$SN}
17130 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Location})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017131 { # duplicated problems for versioned symbols
17132 next;
17133 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017134 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017135 next if($Type_Name ne $Target_TypeName);
17136
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017137 my $Position = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Param_Pos"};
17138 my $Param_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Param_Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017139 my $Severity = getProblemSeverity($Level, $Kind);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017140 my $Path_Length = 0;
17141 my $ProblemLocation = $Location;
17142 if($Type_Name) {
17143 $ProblemLocation=~s/->\Q$Type_Name\E\Z//g;
17144 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017145 while($ProblemLocation=~/\-\>/g) {
17146 $Path_Length += 1;
17147 }
17148 if($MinPath_Length==-1 or ($Path_Length<=$MinPath_Length and $Severity_Val{$Severity}>$Severity_Max)
17149 or (cmp_locations($ProblemLocation, $ProblemLocation_Last) and $Severity_Val{$Severity}==$Severity_Max))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017150 {
17151 $MinPath_Length = $Path_Length;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017152 $Severity_Max = $Severity_Val{$Severity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017153 $ProblemLocation_Last = $ProblemLocation;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017154 %{$SProblems{$Symbol}} = (
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017155 "Descr"=>getAffectDescription($Level, $Symbol, $Kind, $Location),
17156 "Severity_Max"=>$Severity_Max,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017157 "Signature"=>$Signature,
17158 "Position"=>$Position,
17159 "Param_Name"=>$Param_Name,
17160 "Location"=>$Location
17161 );
17162 }
17163 }
17164 }
17165 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017166 my @Symbols = keys(%SProblems);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017167 @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 +040017168 @Symbols = sort {$SProblems{$b}{"Severity_Max"}<=>$SProblems{$a}{"Severity_Max"}} @Symbols;
17169 if($#Symbols+1>$LIMIT)
17170 { # remove last element
17171 pop(@Symbols);
17172 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017173 my $Affected = "";
17174 if($ReportFormat eq "xml")
17175 { # XML
17176 $Affected .= " <affected>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017177 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017178 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017179 my $Param_Name = $SProblems{$Symbol}{"Param_Name"};
17180 my $Description = $SProblems{$Symbol}{"Descr"};
17181 my $Location = $SProblems{$Symbol}{"Location"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017182 my $Target = "";
17183 if($Param_Name) {
17184 $Target = " affected=\"param\" param_name=\"$Param_Name\"";
17185 }
17186 elsif($Location=~/\Aretval(\-|\Z)/i) {
17187 $Target = " affected=\"retval\"";
17188 }
17189 elsif($Location=~/\Athis(\-|\Z)/i) {
17190 $Target = " affected=\"this\"";
17191 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017192 $Affected .= " <symbol$Target name=\"$Symbol\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017193 $Affected .= " <comment>".xmlSpecChars($Description)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017194 $Affected .= " </symbol>\n";
17195 }
17196 $Affected .= " </affected>\n";
17197 }
17198 else
17199 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017200 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017201 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017202 my $Description = $SProblems{$Symbol}{"Descr"};
17203 my $Signature = $SProblems{$Symbol}{"Signature"};
17204 my $Pos = $SProblems{$Symbol}{"Position"};
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017205 $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 +040017206 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017207 if(keys(%SProblems)>$LIMIT) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017208 $Affected .= "and others ...<br/>";
17209 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017210 $Affected = "<div class='affected'>".$Affected."</div>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017211 if($Affected)
17212 {
17213 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017214 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".(keys(%SProblems)>$LIMIT?">".$LIMIT:keys(%SProblems)).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017215 }
17216 }
17217 return $Affected;
17218}
17219
17220sub cmp_locations($$)
17221{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017222 my ($L1, $L2) = @_;
17223 if($L2=~/\b(retval|this)\b/
17224 and $L1!~/\b(retval|this)\b/ and $L1!~/\-\>/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017225 return 1;
17226 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017227 if($L2=~/\b(retval|this)\b/ and $L2=~/\-\>/
17228 and $L1!~/\b(retval|this)\b/ and $L1=~/\-\>/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017229 return 1;
17230 }
17231 return 0;
17232}
17233
17234sub getAffectDescription($$$$)
17235{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017236 my ($Level, $Symbol, $Kind, $Location) = @_;
17237 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017238 my $PPos = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017239 my @Sentence = ();
17240 $Location=~s/\A(.*)\-\>.+?\Z/$1/;
17241 if($Kind eq "Overridden_Virtual_Method"
17242 or $Kind eq "Overridden_Virtual_Method_B") {
17243 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17244 }
17245 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17246 {
17247 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17248 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017249 my $METHOD_TYPE = $CompleteSignature{1}{$Symbol}{"Constructor"}?"constructor":"method";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017250 my $ClassName = $TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017251 if($ClassName eq $Problem{"Type_Name"}) {
17252 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17253 }
17254 else {
17255 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17256 }
17257 }
17258 else
17259 {
17260 if($Location=~/retval/)
17261 { # return value
17262 if($Location=~/\-\>/) {
17263 push(@Sentence, "Field \'".$Location."\' in return value");
17264 }
17265 else {
17266 push(@Sentence, "Return value");
17267 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017268 if(my $Init = $Problem{"InitialType_Type"})
17269 {
17270 if($Init eq "Pointer") {
17271 push(@Sentence, "(pointer)");
17272 }
17273 elsif($Init eq "Ref") {
17274 push(@Sentence, "(reference)");
17275 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017276 }
17277 }
17278 elsif($Location=~/this/)
17279 { # "this" pointer
17280 if($Location=~/\-\>/) {
17281 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17282 }
17283 else {
17284 push(@Sentence, "\'this\' pointer");
17285 }
17286 }
17287 else
17288 { # parameters
17289 if($Location=~/\-\>/) {
17290 push(@Sentence, "Field \'".$Location."\' in $PPos parameter");
17291 }
17292 else {
17293 push(@Sentence, "$PPos parameter");
17294 }
17295 if($Problem{"Param_Name"}) {
17296 push(@Sentence, "\'".$Problem{"Param_Name"}."\'");
17297 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017298 if(my $Init = $Problem{"InitialType_Type"})
17299 {
17300 if($Init eq "Pointer") {
17301 push(@Sentence, "(pointer)");
17302 }
17303 elsif($Init eq "Ref") {
17304 push(@Sentence, "(reference)");
17305 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017306 }
17307 }
17308 if($Location eq "this") {
17309 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17310 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017311 elsif(defined $Problem{"Start_Type_Name"}
17312 and $Problem{"Start_Type_Name"} eq $Problem{"Type_Name"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017313 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17314 }
17315 else {
17316 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17317 }
17318 }
17319 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017320 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017321 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 +040017322 }
17323 return join(" ", @Sentence);
17324}
17325
17326sub get_XmlSign($$)
17327{
17328 my ($Symbol, $LibVersion) = @_;
17329 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17330 my $Report = "";
17331 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17332 {
17333 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017334 my $Type = $Info->{"Param"}{$Pos}{"type"};
17335 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017336 foreach my $Typedef (keys(%ChangedTypedef))
17337 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017338 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17339 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17340 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017341 }
17342 $Report .= " <param pos=\"$Pos\">\n";
17343 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017344 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017345 $Report .= " </param>\n";
17346 }
17347 if(my $Return = $Info->{"Return"})
17348 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017349 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017350 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017351 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017352 $Report .= " </retval>\n";
17353 }
17354 return $Report;
17355}
17356
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017357sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017358{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017359 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017360 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017361 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017362 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017363 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17364 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017365 next;
17366 }
17367 $Report .= " <symbol name=\"$Symbol\">\n";
17368 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017369 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017370 {
17371 if(defined $CompleteSignature{1}{$Symbol}
17372 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17373 {
17374 $P1 = get_XmlSign($Symbol, 1);
17375 $S1 = get_Signature($Symbol, 1);
17376 }
17377 elsif($Symbol=~/\A(_Z|\?)/) {
17378 $S1 = $tr_name{$Symbol};
17379 }
17380 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017381 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017382 {
17383 if(defined $CompleteSignature{2}{$Symbol}
17384 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17385 {
17386 $P2 = get_XmlSign($Symbol, 2);
17387 $S2 = get_Signature($Symbol, 2);
17388 }
17389 elsif($Symbol=~/\A(_Z|\?)/) {
17390 $S2 = $tr_name{$Symbol};
17391 }
17392 }
17393 if($S1)
17394 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017395 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017396 $Report .= $P1;
17397 $Report .= " </old>\n";
17398 }
17399 if($S2 and $S2 ne $S1)
17400 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017401 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017402 $Report .= $P2;
17403 $Report .= " </new>\n";
17404 }
17405 $Report .= " </symbol>\n";
17406 }
17407 $Report .= "</symbols_info>\n";
17408 return $Report;
17409}
17410
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017411sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017412{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017413 my ($Level, $Report) = @_;
17414 if($ReportFormat eq "xml") {
17415 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017416 }
17417 if($StdOut)
17418 { # --stdout option
17419 print STDOUT $Report;
17420 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017421 else
17422 {
17423 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017424 mkpath(get_dirname($RPath));
17425
17426 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17427 print REPORT $Report;
17428 close(REPORT);
17429
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017430 if($Browse or $OpenReport)
17431 { # open in browser
17432 openReport($RPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017433 if($JoinReport or $DoubleReport)
17434 {
17435 if($Level eq "Binary")
17436 { # wait to open a browser
17437 sleep(1);
17438 }
17439 }
17440 }
17441 }
17442}
17443
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017444sub openReport($)
17445{
17446 my $Path = $_[0];
17447 my $Cmd = "";
17448 if($Browse)
17449 { # user-defined browser
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017450 $Cmd = $Browse." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017451 }
17452 if(not $Cmd)
17453 { # default browser
17454 if($OSgroup eq "macos") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017455 $Cmd = "open \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017456 }
17457 elsif($OSgroup eq "windows") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017458 $Cmd = "start ".path_format($Path, $OSgroup);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017459 }
17460 else
17461 { # linux, freebsd, solaris
17462 my @Browsers = (
17463 "x-www-browser",
17464 "sensible-browser",
17465 "firefox",
17466 "opera",
17467 "xdg-open",
17468 "lynx",
17469 "links"
17470 );
17471 foreach my $Br (@Browsers)
17472 {
17473 if($Br = get_CmdPath($Br))
17474 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017475 $Cmd = $Br." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017476 last;
17477 }
17478 }
17479 }
17480 }
17481 if($Cmd)
17482 {
17483 if($Debug) {
17484 printMsg("INFO", "running $Cmd");
17485 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017486 if($OSgroup ne "windows"
17487 and $OSgroup ne "macos")
17488 {
17489 if($Cmd!~/lynx|links/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017490 $Cmd .= " >\"/dev/null\" 2>&1 &";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017491 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017492 }
17493 system($Cmd);
17494 }
17495 else {
17496 printMsg("ERROR", "cannot open report in browser");
17497 }
17498}
17499
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017500sub getReport($)
17501{
17502 my $Level = $_[0];
17503 if($ReportFormat eq "xml")
17504 { # XML
17505
17506 if($Level eq "Join")
17507 {
17508 my $Report = "<reports>\n";
17509 $Report .= getReport("Binary");
17510 $Report .= getReport("Source");
17511 $Report .= "</reports>\n";
17512 return $Report;
17513 }
17514 else
17515 {
17516 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17517 my ($Summary, $MetaData) = get_Summary($Level);
17518 $Report .= $Summary."\n";
17519 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17520 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17521 $Report .= get_Report_SymbolsInfo($Level);
17522 $Report .= "</report>\n";
17523 return $Report;
17524 }
17525 }
17526 else
17527 { # HTML
17528 my $CssStyles = readModule("Styles", "Report.css");
17529 my $JScripts = readModule("Scripts", "Sections.js");
17530 if($Level eq "Join")
17531 {
17532 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17533 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040017534 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
17535 my $Keywords = $TargetLibraryFName.", compatibility, API, report";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017536 my $Description = "Compatibility report for the $TargetLibraryFName $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
17537 my ($BSummary, $BMetaData) = get_Summary("Binary");
17538 my ($SSummary, $SMetaData) = get_Summary("Source");
17539 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>";
17540 $Report .= get_Report_Header("Join")."
17541 <br/><div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017542 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17543 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017544 </div>";
17545 $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>";
17546 $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 +040017547 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017548 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
17549 return $Report;
17550 }
17551 else
17552 {
17553 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040017554 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17555 my $Keywords = $TargetLibraryFName.", ".lc($Level)." compatibility, API, report";
17556 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 +040017557 if($Level eq "Binary")
17558 {
17559 if(getArch(1) eq getArch(2)
17560 and getArch(1) ne "unknown") {
17561 $Description .= " on ".showArch(getArch(1));
17562 }
17563 }
17564 my $Report = "<!-\- $MetaData -\->\n".composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."\n<body>\n<div><a name='Top'></a>\n";
17565 $Report .= get_Report_Header($Level)."\n".$Summary."\n";
17566 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17567 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17568 $Report .= get_SourceInfo();
17569 $Report .= "</div>\n<br/><br/><br/><hr/>\n";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017570 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017571 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
17572 return $Report;
17573 }
17574 }
17575}
17576
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017577sub getLegend()
17578{
17579 return "<br/>
17580<table class='summary'>
17581<tr>
17582 <td class='new'>added</td>
17583 <td class='passed'>compatible</td>
17584</tr>
17585<tr>
17586 <td class='warning'>warning</td>
17587 <td class='failed'>incompatible</td>
17588</tr></table>\n";
17589}
17590
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017591sub createReport()
17592{
17593 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017594 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017595 writeReport("Join", getReport("Join"));
17596 }
17597 elsif($DoubleReport)
17598 { # default
17599 writeReport("Binary", getReport("Binary"));
17600 writeReport("Source", getReport("Source"));
17601 }
17602 elsif($BinaryOnly)
17603 { # --binary
17604 writeReport("Binary", getReport("Binary"));
17605 }
17606 elsif($SourceOnly)
17607 { # --source
17608 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017609 }
17610}
17611
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017612sub getReportFooter($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017613{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017614 my ($LibName, $Wide) = @_;
17615 my $FooterStyle = $Wide?"width:99%":"width:97%;padding-top:3px";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017616 my $Footer = "<div style='$FooterStyle;font-size:11px;' align='right'><i>Generated on ".(localtime time); # report date
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017617 $Footer .= " for <span style='font-weight:bold'>$LibName</span>"; # tested library/system name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017618 $Footer .= " by <a href='".$HomePage{"Wiki"}."'>ABI Compliance Checker</a>"; # tool name
17619 my $ToolSummary = "<br/>A tool for checking backward compatibility of a C/C++ library API&#160;&#160;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017620 $Footer .= " $TOOL_VERSION &#160;$ToolSummary</i></div>"; # tool version
17621 return $Footer;
17622}
17623
17624sub get_Report_Problems($$)
17625{
17626 my ($Priority, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017627 my $Report = get_Report_TypeProblems($Priority, $Level);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017628 if(my $SProblems = get_Report_SymbolProblems($Priority, $Level)) {
17629 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017630 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017631 if($Priority eq "Low")
17632 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017633 $Report .= get_Report_ChangedConstants("Low", $Level);
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +040017634 if($ReportFormat eq "html")
17635 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017636 if($CheckImpl and $Level eq "Binary") {
17637 $Report .= get_Report_Impl();
17638 }
17639 }
17640 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017641 if($Priority eq "Safe")
17642 {
17643 $Report .= get_Report_ChangedConstants("Safe", $Level);
17644 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017645 if($ReportFormat eq "html")
17646 {
17647 if($Report)
17648 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017649 if($JoinReport)
17650 {
17651 if($Priority eq "Safe") {
17652 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17653 }
17654 else {
17655 $Report = "<a name=\'".$Priority."_Risk_".$Level."_Problems\'></a>".$Report;
17656 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017657 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017658 else
17659 {
17660 if($Priority eq "Safe") {
17661 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17662 }
17663 else {
17664 $Report = "<a name=\'".$Priority."_Risk_Problems\'></a>".$Report;
17665 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017666 }
17667 }
17668 }
17669 return $Report;
17670}
17671
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017672sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017673{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017674 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17675 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17676 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17677 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017678 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17679 <meta name=\"keywords\" content=\"$Keywords\" />
17680 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017681 <title>
17682 $Title
17683 </title>
17684 <style type=\"text/css\">
17685 $Styles
17686 </style>
17687 <script type=\"text/javascript\" language=\"JavaScript\">
17688 <!--
17689 $Scripts
17690 -->
17691 </script>
17692 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017693}
17694
17695sub insertIDs($)
17696{
17697 my $Text = $_[0];
17698 while($Text=~/CONTENT_ID/)
17699 {
17700 if(int($Content_Counter)%2) {
17701 $ContentID -= 1;
17702 }
17703 $Text=~s/CONTENT_ID/c_$ContentID/;
17704 $ContentID += 1;
17705 $Content_Counter += 1;
17706 }
17707 return $Text;
17708}
17709
17710sub checkPreprocessedUnit($)
17711{
17712 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017713 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017714 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017715 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017716
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017717 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017718 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017719 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017720 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017721 chomp($Line);
17722 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017723 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017724 $CurHeader = path_format($1, $OSgroup);
17725 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017726 $CurClass = "";
17727
17728 if(index($CurHeader, $TMP_DIR)==0) {
17729 next;
17730 }
17731
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017732 if(substr($CurHeaderName, 0, 1) eq "<")
17733 { # <built-in>, <command-line>, etc.
17734 $CurHeaderName = "";
17735 $CurHeader = "";
17736 }
17737
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017738 if($ExtraInfo)
17739 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017740 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017741 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17742 }
17743 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017744 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017745 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017746 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017747 if($CurHeaderName)
17748 {
17749 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17750 and not $Registered_Headers{$Version}{$CurHeader})
17751 { # not a target
17752 next;
17753 }
17754 if(not is_target_header($CurHeaderName, 1)
17755 and not is_target_header($CurHeaderName, 2))
17756 { # user-defined header
17757 next;
17758 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017759 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017760 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017761
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017762 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017763 {
17764 my ($Name, $Value) = ($1, $2);
17765 if(not $Constants{$Version}{$Name}{"Access"})
17766 {
17767 $Constants{$Version}{$Name}{"Access"} = "public";
17768 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017769 if($CurHeaderName) {
17770 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17771 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017772 }
17773 }
17774 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17775 $Constants{$Version}{$1}{"Access"} = "private";
17776 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017777 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017778 else
17779 {
17780 if(defined $ExtraDump)
17781 {
17782 if($Line=~/(\w+)\s*\(/)
17783 { # functions
17784 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17785 }
17786 #elsif($Line=~/(\w+)\s*;/)
17787 #{ # data
17788 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17789 #}
17790 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17791 $CurClass = $2;
17792 }
17793 }
17794 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017795 }
17796 close(PREPROC);
17797 foreach my $Constant (keys(%{$Constants{$Version}}))
17798 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017799 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17800 {
17801 delete($Constants{$Version}{$Constant});
17802 next;
17803 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017804 if(not $ExtraDump and ($Constant=~/_h\Z/i
17805 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017806 { # skip
17807 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017808 }
17809 else {
17810 delete($Constants{$Version}{$Constant}{"Access"});
17811 }
17812 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017813 if($Debug)
17814 {
17815 mkpath($DEBUG_PATH{$Version});
17816 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17817 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017818}
17819
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017820sub uncoverConstant($$)
17821{
17822 my ($LibVersion, $Constant) = @_;
17823 return "" if(not $LibVersion or not $Constant);
17824 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17825 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17826 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17827 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017828
17829 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017830 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017831 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17832 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017833 {
17834 push(@RecurConstant, $Constant);
17835 my $Uncovered = uncoverConstant($LibVersion, $Value);
17836 if($Uncovered ne "") {
17837 $Value = $Uncovered;
17838 }
17839 pop(@RecurConstant);
17840 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017841
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017842 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017843 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017844 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17845 }
17846 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17847}
17848
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017849sub simpleConstant($$)
17850{
17851 my ($LibVersion, $Value) = @_;
17852 if($Value=~/\W/)
17853 {
17854 my $Value_Copy = $Value;
17855 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
17856 {
17857 my $Word = $1;
17858 if($Value!~/$Word\s*\(/)
17859 {
17860 my $Val = uncoverConstant($LibVersion, $Word);
17861 if($Val ne "")
17862 {
17863 $Value=~s/\b$Word\b/$Val/g;
17864 }
17865 }
17866 }
17867 }
17868 return $Value;
17869}
17870
17871sub computeValue($)
17872{
17873 my $Value = $_[0];
17874
17875 if($Value=~/\A\((-?[\d]+)\)\Z/) {
17876 return $1;
17877 }
17878
17879 if($Value=~/\A[\d\-\+()]+\Z/) {
17880 return eval($Value);
17881 }
17882
17883 return $Value;
17884}
17885
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017886my %IgnoreConstant = map {$_=>1} (
17887 "VERSION",
17888 "VERSIONCODE",
17889 "VERNUM",
17890 "VERS_INFO",
17891 "PATCHLEVEL",
17892 "INSTALLPREFIX",
17893 "VBUILD",
17894 "VPATCH",
17895 "VMINOR",
17896 "BUILD_STRING",
17897 "BUILD_TIME",
17898 "PACKAGE_STRING",
17899 "PRODUCTION",
17900 "CONFIGURE_COMMAND",
17901 "INSTALLDIR",
17902 "BINDIR",
17903 "CONFIG_FILE_PATH",
17904 "DATADIR",
17905 "EXTENSION_DIR",
17906 "INCLUDE_PATH",
17907 "LIBDIR",
17908 "LOCALSTATEDIR",
17909 "SBINDIR",
17910 "SYSCONFDIR",
17911 "RELEASE",
17912 "SOURCE_ID",
17913 "SUBMINOR",
17914 "MINOR",
17915 "MINNOR",
17916 "MINORVERSION",
17917 "MAJOR",
17918 "MAJORVERSION",
17919 "MICRO",
17920 "MICROVERSION",
17921 "BINARY_AGE",
17922 "INTERFACE_AGE",
17923 "CORE_ABI",
17924 "PATCH",
17925 "COPYRIGHT",
17926 "TIMESTAMP",
17927 "REVISION",
17928 "PACKAGE_TAG",
17929 "PACKAGEDATE",
17930 "NUMVERSION",
17931 "Release",
17932 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017933);
17934
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017935sub constantFilter($$$)
17936{
17937 my ($Name, $Value, $Level) = @_;
17938
17939 if($Level eq "Binary")
17940 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017941 if($Name=~/_t\Z/)
17942 { # __malloc_ptr_t
17943 return 1;
17944 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017945 foreach (keys(%IgnoreConstant))
17946 {
17947 if($Name=~/(\A|_)$_(_|\Z)/)
17948 { # version
17949 return 1;
17950 }
17951 if(/\A[A-Z].*[a-z]\Z/)
17952 {
17953 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
17954 { # version
17955 return 1;
17956 }
17957 }
17958 }
17959 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
17960 { # version
17961 return 1;
17962 }
17963 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
17964 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
17965 return 1;
17966 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017967
17968 if($Value=~/\A["'].*['"]/i)
17969 { # string
17970 return 0;
17971 }
17972
17973 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
17974 { # static int gcry_pth_init
17975 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017976 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017977 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017978 return 1;
17979 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017980 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017981 { # foo(p)
17982 return 1;
17983 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017984 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017985 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017986 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017987 return 1;
17988 }
17989 }
17990
17991 return 0;
17992}
17993
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017994sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017995{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017996 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017997 foreach my $Constant (keys(%{$Constants{1}}))
17998 {
17999 if($SkipConstants{1}{$Constant})
18000 { # skipped by the user
18001 next;
18002 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018003
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018004 if(my $Header = $Constants{1}{$Constant}{"Header"})
18005 {
18006 if(not is_target_header($Header, 1)
18007 and not is_target_header($Header, 2))
18008 { # user-defined header
18009 next;
18010 }
18011 }
18012 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018013 next;
18014 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018015
18016 my $Old_Value = uncoverConstant(1, $Constant);
18017
18018 if(constantFilter($Constant, $Old_Value, $Level))
18019 { # separate binary and source problems
18020 next;
18021 }
18022
18023 if(not defined $Constants{2}{$Constant}{"Value"})
18024 { # removed
18025 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18026 "Target"=>$Constant,
18027 "Old_Value"=>$Old_Value );
18028 next;
18029 }
18030
18031 if($Constants{2}{$Constant}{"Value"} eq "")
18032 { # empty value
18033 # TODO: implement a rule
18034 next;
18035 }
18036
18037 my $New_Value = uncoverConstant(2, $Constant);
18038
18039 my $Old_Value_Pure = $Old_Value;
18040 my $New_Value_Pure = $New_Value;
18041
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018042 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18043 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18044 $New_Value_Pure=~s/(\W)\s+/$1/g;
18045 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018046
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018047 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018048
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018049 if($New_Value_Pure ne $Old_Value_Pure)
18050 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018051 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18052 { # complex values
18053 next;
18054 }
18055 if(computeValue($Old_Value) eq computeValue($New_Value))
18056 { # expressions
18057 next;
18058 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018059 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18060 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18061 next;
18062 }
18063 if($Old_Value eq "0" and $New_Value eq "NULL")
18064 { # 0 => NULL
18065 next;
18066 }
18067 if($Old_Value eq "NULL" and $New_Value eq "0")
18068 { # NULL => 0
18069 next;
18070 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018071 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018072 "Target"=>$Constant,
18073 "Old_Value"=>$Old_Value,
18074 "New_Value"=>$New_Value );
18075 }
18076 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018077
18078 foreach my $Constant (keys(%{$Constants{2}}))
18079 {
18080 if(not defined $Constants{1}{$Constant}{"Value"})
18081 {
18082 if($SkipConstants{2}{$Constant})
18083 { # skipped by the user
18084 next;
18085 }
18086
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018087 if(my $Header = $Constants{2}{$Constant}{"Header"})
18088 {
18089 if(not is_target_header($Header, 1)
18090 and not is_target_header($Header, 2))
18091 { # user-defined header
18092 next;
18093 }
18094 }
18095 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018096 next;
18097 }
18098
18099 my $New_Value = uncoverConstant(2, $Constant);
18100 if(not defined $New_Value or $New_Value eq "") {
18101 next;
18102 }
18103
18104 if(constantFilter($Constant, $New_Value, $Level))
18105 { # separate binary and source problems
18106 next;
18107 }
18108
18109 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18110 "Target"=>$Constant,
18111 "New_Value"=>$New_Value );
18112 }
18113 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018114}
18115
18116sub convert_integer($)
18117{
18118 my $Value = $_[0];
18119 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018120 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018121 return hex($Value);
18122 }
18123 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018124 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018125 return oct($Value);
18126 }
18127 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018128 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018129 return oct($Value);
18130 }
18131 else {
18132 return $Value;
18133 }
18134}
18135
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018136sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018137{
18138 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018139 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018140 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018141 {
18142 if($LibVersion==1)
18143 {
18144 printMsg("WARNING", "checking headers only");
18145 $CheckHeadersOnly = 1;
18146 }
18147 else {
18148 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18149 }
18150 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018151
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018152 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018153 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018154 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018155
18156 if($CheckUndefined)
18157 {
18158 my %UndefinedLibs = ();
18159
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018160 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18161
18162 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018163 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018164 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018165 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018166 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018167 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018168 if($Symbol_Library{$LibVersion}{$Symbol}
18169 or $DepSymbol_Library{$LibVersion}{$Symbol})
18170 { # exported by target library
18171 next;
18172 }
18173 if(index($Symbol, '@')!=-1)
18174 { # exported default symbol version (@@)
18175 $Symbol=~s/\@/\@\@/;
18176 if($Symbol_Library{$LibVersion}{$Symbol}
18177 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18178 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018179 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018180 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018181 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18182 $UndefinedLibs{$Path} = 1;
18183 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018184 }
18185 }
18186 }
18187 if($ExtraInfo)
18188 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018189 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018190 {
18191 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018192 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018193 foreach (@Paths)
18194 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018195 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018196 my ($Dir, $Name) = separate_path($_);
18197
18198 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018199 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018200 }
18201
18202 $Name = parse_libname($Name, "name", $OStarget);
18203 $Name=~s/\Alib//;
18204
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018205 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018206 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018207
18208 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18209 {
18210 $LibString = " -L".esc($Dir).$LibString;
18211 }
18212
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018213 writeFile($ExtraInfo."/libs-string", $LibString);
18214 }
18215 }
18216 }
18217
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018218 if($ExtraInfo) {
18219 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18220 }
18221
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018222 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018223 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018224 if($#LibPaths!=-1)
18225 {
18226 if(not keys(%{$Symbol_Library{$LibVersion}}))
18227 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018228 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018229 printMsg("WARNING", "checking headers only");
18230 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018231 }
18232 }
18233 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018234
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018235 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018236 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018237}
18238
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018239my %Prefix_Lib_Map=(
18240 # symbols for autodetecting library dependencies (by prefix)
18241 "pthread_" => ["libpthread"],
18242 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18243 "cairo_" => ["libcairo"],
18244 "gtk_" => ["libgtk-x11-2.0"],
18245 "atk_" => ["libatk-1.0"],
18246 "gdk_" => ["libgdk-x11-2.0"],
18247 "gl" => ["libGL"],
18248 "glu" => ["libGLU"],
18249 "popt" => ["libpopt"],
18250 "Py" => ["libpython"],
18251 "jpeg_" => ["libjpeg"],
18252 "BZ2_" => ["libbz2"],
18253 "Fc" => ["libfontconfig"],
18254 "Xft" => ["libXft"],
18255 "SSL_" => ["libssl"],
18256 "sem_" => ["libpthread"],
18257 "snd_" => ["libasound"],
18258 "art_" => ["libart_lgpl_2"],
18259 "dbus_g" => ["libdbus-glib-1"],
18260 "GOMP_" => ["libgomp"],
18261 "omp_" => ["libgomp"],
18262 "cms" => ["liblcms"]
18263);
18264
18265my %Pattern_Lib_Map=(
18266 "SL[a-z]" => ["libslang"]
18267);
18268
18269my %Symbol_Lib_Map=(
18270 # symbols for autodetecting library dependencies (by name)
18271 "pow" => "libm",
18272 "fmod" => "libm",
18273 "sin" => "libm",
18274 "floor" => "libm",
18275 "cos" => "libm",
18276 "dlopen" => "libdl",
18277 "deflate" => "libz",
18278 "inflate" => "libz",
18279 "move_panel" => "libpanel",
18280 "XOpenDisplay" => "libX11",
18281 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018282 "clock_gettime" => "librt",
18283 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018284);
18285
18286sub find_SymbolLibs($$)
18287{
18288 my ($LibVersion, $Symbol) = @_;
18289
18290 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18291 { # debug symbols
18292 return ();
18293 }
18294
18295 my %Paths = ();
18296
18297 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18298 {
18299 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18300 $Paths{$Path} = 1;
18301 }
18302 }
18303
18304 if(my $SymbolPrefix = getPrefix($Symbol))
18305 {
18306 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18307 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18308 }
18309
18310 if(not keys(%Paths))
18311 {
18312 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18313 {
18314 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18315 {
18316 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18317 $Paths{$Path} = 1;
18318 }
18319 }
18320 }
18321 }
18322
18323 if(not keys(%Paths))
18324 {
18325 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18326 {
18327 if($Symbol=~/\A$Prefix/)
18328 {
18329 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18330 {
18331 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18332 $Paths{$Path} = 1;
18333 }
18334 }
18335 }
18336 }
18337 }
18338
18339 if(not keys(%Paths))
18340 {
18341 if($SymbolPrefix)
18342 { # try to find a library by symbol prefix
18343 if($SymbolPrefix eq "inotify" and
18344 index($Symbol, "\@GLIBC")!=-1)
18345 {
18346 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18347 $Paths{$Path} = 1;
18348 }
18349 }
18350 else
18351 {
18352 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18353 $Paths{$Path} = 1;
18354 }
18355 }
18356 }
18357 }
18358
18359 if(my @Paths = keys(%Paths)) {
18360 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18361 }
18362 }
18363 return keys(%Paths);
18364}
18365
18366sub get_LibPath_Prefix($$)
18367{
18368 my ($LibVersion, $Prefix) = @_;
18369
18370 $Prefix = lc($Prefix);
18371 $Prefix=~s/[_]+\Z//g;
18372
18373 foreach ("-2", "2", "-1", "1", "")
18374 { # libgnome-2.so
18375 # libxml2.so
18376 # libdbus-1.so
18377 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18378 return $Path;
18379 }
18380 }
18381 return "";
18382}
18383
18384sub getPrefix($)
18385{
18386 my $Str = $_[0];
18387 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18388 { # XmuValidArea: Xmu
18389 return $1;
18390 }
18391 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18392 { # snfReadFont: snf
18393 return $1;
18394 }
18395 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18396 { # XRRTimes: XRR
18397 return $1;
18398 }
18399 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18400 { # H5HF_delete: H5
18401 return $1;
18402 }
18403 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18404 { # alarm_event_add: alarm_
18405 return $1;
18406 }
18407 elsif($Str=~/\A(([a-z])\2{1,})/i)
18408 { # ffopen
18409 return $1;
18410 }
18411 return "";
18412}
18413
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018414sub getSymbolSize($$)
18415{ # size from the shared library
18416 my ($Symbol, $LibVersion) = @_;
18417 return 0 if(not $Symbol);
18418 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18419 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18420 {
18421 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18422 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18423 {
18424 if($Size<0) {
18425 return -$Size;
18426 }
18427 }
18428 }
18429 return 0;
18430}
18431
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018432sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018433{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18434 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018435 my ($Name, $Type) = @_;
18436
18437 # single
18438 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018439 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018440 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018441 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018442 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018443
18444 # double
18445 if($Name=~/$DEFAULT_STD_PARMS/)
18446 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018447 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018448 {
18449 my ($ShortName, $FuncParams) = split_Signature($Name);
18450
18451 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18452 {
18453 if(index($FParam, "<")!=-1)
18454 {
18455 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18456 my $FParam_N = canonifyName($FParam, "T");
18457 if($FParam_N ne $FParam) {
18458 $Name=~s/\Q$FParam\E/$FParam_N/g;
18459 }
18460 }
18461 }
18462 }
18463 elsif($Type eq "T")
18464 {
18465 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18466
18467 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018468 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018469 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018470 my $FParam = $TParams[0];
18471 foreach my $Pos (1 .. $#TParams)
18472 {
18473 my $TParam = $TParams[$Pos];
18474 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18475 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18476 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018477 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018478 }
18479 }
18480 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018481 if($Type eq "S") {
18482 return formatName($Name, "S");
18483 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018484 return $Name;
18485}
18486
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018487sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018488{
18489 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018490 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018491 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018492 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018493 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018494 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018495 next if($tr_name{$Symbol});
18496 $Symbol=~s/[\@\$]+(.*)\Z//;
18497 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018498 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018499 elsif(index($Symbol, "?")==0)
18500 {
18501 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018502 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018503 }
18504 else
18505 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018506 $tr_name{$Symbol} = $Symbol;
18507 $mangled_name_gcc{$Symbol} = $Symbol;
18508 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018509 }
18510 }
18511 if($#MnglNames1 > -1)
18512 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018513 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018514 foreach my $MnglName (@MnglNames1)
18515 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018516 if(my $Unmangled = pop(@UnmangledNames))
18517 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018518 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018519 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18520 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18521 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018522 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018523 and $tr_name{$MnglName}=~/vtable for (.+)/)
18524 { # bind class name and v-table symbol
18525 my $ClassName = $1;
18526 $ClassVTable{$ClassName} = $MnglName;
18527 $VTableClass{$MnglName} = $ClassName;
18528 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018529 }
18530 }
18531 }
18532 if($#MnglNames2 > -1)
18533 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018534 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018535 foreach my $MnglName (@MnglNames2)
18536 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018537 if(my $Unmangled = pop(@UnmangledNames))
18538 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018539 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018540 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18541 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018542 }
18543 }
18544 return \%tr_name;
18545}
18546
18547sub link_symbol($$$)
18548{
18549 my ($Symbol, $RunWith, $Deps) = @_;
18550 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18551 return 1;
18552 }
18553 if($Deps eq "+Deps")
18554 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018555 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018556 return 1;
18557 }
18558 }
18559 return 0;
18560}
18561
18562sub link_symbol_internal($$$)
18563{
18564 my ($Symbol, $RunWith, $Where) = @_;
18565 return 0 if(not $Where or not $Symbol);
18566 if($Where->{$RunWith}{$Symbol})
18567 { # the exact match by symbol name
18568 return 1;
18569 }
18570 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18571 { # indirect symbol version, i.e.
18572 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018573 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018574 if($Where->{$RunWith}{$VSym}) {
18575 return 1;
18576 }
18577 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018578 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018579 if($Sym and $Ver)
18580 { # search for the symbol with the same version
18581 # or without version
18582 if($Where->{$RunWith}{$Sym})
18583 { # old: foo@v|foo@@v
18584 # new: foo
18585 return 1;
18586 }
18587 if($Where->{$RunWith}{$Sym."\@".$Ver})
18588 { # old: foo|foo@@v
18589 # new: foo@v
18590 return 1;
18591 }
18592 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18593 { # old: foo|foo@v
18594 # new: foo@@v
18595 return 1;
18596 }
18597 }
18598 return 0;
18599}
18600
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018601sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018602{
18603 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018604 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018605 my @Imported = ();
18606 if($OSgroup eq "macos")
18607 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018608 my $NM = get_CmdPath("nm");
18609 if(not $NM) {
18610 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018611 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018612 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018613 while(<APP>)
18614 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018615 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018616 push(@Imported, $1);
18617 }
18618 }
18619 close(APP);
18620 }
18621 elsif($OSgroup eq "windows")
18622 {
18623 my $DumpBinCmd = get_CmdPath("dumpbin");
18624 if(not $DumpBinCmd) {
18625 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18626 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018627 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018628 while(<APP>)
18629 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018630 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18631 push(@Imported, $1);
18632 }
18633 }
18634 close(APP);
18635 }
18636 else
18637 {
18638 my $ReadelfCmd = get_CmdPath("readelf");
18639 if(not $ReadelfCmd) {
18640 exitStatus("Not_Found", "can't find \"readelf\"");
18641 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018642 open(APP, "$ReadelfCmd -WhlSsdA \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018643 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018644 while(<APP>)
18645 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018646 if(defined $symtab)
18647 { # do nothing with symtab
18648 if(index($_, "'.dynsym'")!=-1)
18649 { # dynamic table
18650 $symtab = undef;
18651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018652 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018653 elsif(index($_, "'.symtab'")!=-1)
18654 { # symbol table
18655 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018656 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018657 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018658 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018659 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18660 if($Ndx eq "UND")
18661 { # only imported symbols
18662 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018663 }
18664 }
18665 }
18666 close(APP);
18667 }
18668 return @Imported;
18669}
18670
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018671my %ELF_BIND = map {$_=>1} (
18672 "WEAK",
18673 "GLOBAL"
18674);
18675
18676my %ELF_TYPE = map {$_=>1} (
18677 "FUNC",
18678 "IFUNC",
18679 "OBJECT",
18680 "COMMON"
18681);
18682
18683my %ELF_VIS = map {$_=>1} (
18684 "DEFAULT",
18685 "PROTECTED"
18686);
18687
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018688sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018689{ # read the line of 'readelf' output corresponding to the symbol
18690 my @Info = split(/\s+/, $_[0]);
18691 # Num: Value Size Type Bind Vis Ndx Name
18692 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018693 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018694 shift(@Info); # spaces
18695 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018696
18697 if($#Info==7)
18698 { # UND SYMBOL (N)
18699 if($Info[7]=~/\(\d+\)/) {
18700 pop(@Info);
18701 }
18702 }
18703
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018704 if($#Info!=6)
18705 { # other lines
18706 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018707 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018708 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018709 return () if(not defined $ELF_BIND{$Info[3]});
18710 return () if(not defined $ELF_VIS{$Info[4]});
18711 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18712 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18713 return ();
18714 }
18715 if($OStarget eq "symbian")
18716 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18717 if(index($Info[6], "_._.absent_export_")!=-1)
18718 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18719 return ();
18720 }
18721 $Info[6]=~s/\@.+//g; # remove version
18722 }
18723 if(index($Info[2], "0x") == 0)
18724 { # size == 0x3d158
18725 $Info[2] = hex($Info[2]);
18726 }
18727 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018728}
18729
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018730sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018731{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018732 my ($LibVersion, $Name) = @_;
18733 return "" if(not $LibVersion or not $Name);
18734 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18735 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018736 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018737 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18738}
18739
18740sub get_LibPath_I($$)
18741{
18742 my ($LibVersion, $Name) = @_;
18743 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018744 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018745 if(-f $Name)
18746 { # absolute path
18747 return $Name;
18748 }
18749 else
18750 { # broken
18751 return "";
18752 }
18753 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018754 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018755 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018756 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018757 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018758 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018759 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018760 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018761 }
18762 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18763 { # ldconfig default paths
18764 return $DefaultPath;
18765 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018766 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018767 { # search in default linker directories
18768 # and then in all system paths
18769 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018770 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018771 }
18772 }
18773 detectSystemObjects() if(not keys(%SystemObjects));
18774 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18775 return $AllObjects[0];
18776 }
18777 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18778 {
18779 if($ShortName ne $Name)
18780 { # FIXME: check this case
18781 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18782 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018783 }
18784 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018785 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018786 # can't find
18787 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018788}
18789
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018790sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018791{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018792 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18793 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018794
18795 my $Real_Path = realpath($Lib_Path);
18796
18797 if(not $Real_Path)
18798 { # broken link
18799 return ();
18800 }
18801
18802 my $Lib_Name = get_filename($Real_Path);
18803
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018804 if($ExtraInfo)
18805 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018806 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018807 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018808 }
18809
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018810 if($IsNeededLib)
18811 {
18812 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18813 return ();
18814 }
18815 }
18816 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018817 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018818
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018819 if($CheckImpl)
18820 {
18821 if(not $IsNeededLib) {
18822 getImplementations($LibVersion, $Lib_Path);
18823 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018824 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018825
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018826 push(@RecurLib, $Lib_Name);
18827 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018828 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18829
18830 if(not $IsNeededLib)
18831 { # special cases: libstdc++ and libc
18832 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18833 {
18834 if($ShortName eq "libstdc++")
18835 { # libstdc++.so.6
18836 $STDCXX_TESTING = 1;
18837 }
18838 elsif($ShortName eq "libc")
18839 { # libc-2.11.3.so
18840 $GLIBC_TESTING = 1;
18841 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018842 }
18843 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018844 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018845 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018846 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018847 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018848 mkpath(get_dirname($DebugPath));
18849 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018850 if($OStarget eq "macos")
18851 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018852 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018853 if(not $NM) {
18854 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018855 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018856 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018857 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018858 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018859 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018860 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018861 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018862 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018863 else
18864 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018865 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018866 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018867 while(<LIB>)
18868 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018869 if($CheckUndefined)
18870 {
18871 if(not $IsNeededLib)
18872 {
18873 if(/ U _([\w\$]+)\s*\Z/)
18874 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018875 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018876 next;
18877 }
18878 }
18879 }
18880
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018881 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018882 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018883 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018884 if($IsNeededLib)
18885 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018886 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018887 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018888 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18889 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018890 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018891 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018892 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018893 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018894 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18895 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018896 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18897 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018898 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018899 setLanguage($LibVersion, "C++");
18900 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018901 }
18902 if($CheckObjectsOnly
18903 and $LibVersion==1) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018904 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018905 }
18906 }
18907 }
18908 }
18909 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018910
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018911 if($Deps)
18912 {
18913 if($LIB_TYPE eq "dynamic")
18914 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018915
18916 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018917 if(not $OtoolCmd) {
18918 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018919 }
18920
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018921 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18922 while(<LIB>)
18923 {
18924 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
18925 and $1 ne $Lib_Path) {
18926 $NeededLib{$1} = 1;
18927 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018928 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018929 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018930 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018931 }
18932 }
18933 elsif($OStarget eq "windows")
18934 { # Windows *.dll, *.lib
18935 my $DumpBinCmd = get_CmdPath("dumpbin");
18936 if(not $DumpBinCmd) {
18937 exitStatus("Not_Found", "can't find \"dumpbin\"");
18938 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018939 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018940 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018941 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018942 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018943 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018944 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018945 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018946 else
18947 { # write to pipe
18948 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018949 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018950 while(<LIB>)
18951 { # 1197 4AC 0000A620 SetThreadStackGuarantee
18952 # 1198 4AD SetThreadToken (forwarded to ...)
18953 # 3368 _o2i_ECPublicKey
18954 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*\Z/i
18955 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
18956 or /\A\s*\d+\s+_([\w\?\@]+)\s*\Z/)
18957 { # dynamic, static and forwarded symbols
18958 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018959 if($IsNeededLib)
18960 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018961 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018962 {
18963 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
18964 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
18965 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018966 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018967 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018968 {
18969 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
18970 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018971 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18972 {
18973 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
18974 setLanguage($LibVersion, "C++");
18975 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018976 }
18977 if($CheckObjectsOnly
18978 and $LibVersion==1) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018979 $CheckedSymbols{"Binary"}{$realname} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018980 }
18981 }
18982 }
18983 }
18984 close(LIB);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018985 if($Deps)
18986 {
18987 if($LIB_TYPE eq "dynamic")
18988 { # dependencies
18989 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18990 while(<LIB>)
18991 {
18992 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
18993 and $1 ne $Lib_Path) {
18994 $NeededLib{path_format($1, $OSgroup)} = 1;
18995 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018996 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018997 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018998 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018999 }
19000 }
19001 else
19002 { # Unix; *.so, *.a
19003 # Symbian: *.dso, *.lib
19004 my $ReadelfCmd = get_CmdPath("readelf");
19005 if(not $ReadelfCmd) {
19006 exitStatus("Not_Found", "can't find \"readelf\"");
19007 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019008 $ReadelfCmd .= " -WhlSsdA \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19009 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019010 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019011 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019012 system($ReadelfCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019013 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019014 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019015 else
19016 { # write to pipe
19017 open(LIB, $ReadelfCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019018 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019019 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019020 while(<LIB>)
19021 {
19022 if($LIB_TYPE eq "dynamic")
19023 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019024 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019025 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019026 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019027 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019028 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019029 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019030 # do nothing with symtab
19031 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019032 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019033 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019034 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019035 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019036 next;
19037 }
19038 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019039 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019040 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019041 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019042 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019043 if($CheckUndefined)
19044 {
19045 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019046 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019047 }
19048 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019049 next;
19050 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019051 if($Bind eq "WEAK")
19052 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019053 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019054 if($Weak eq "-Weak")
19055 { # skip WEAK symbols
19056 next;
19057 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019058 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019059 my $Short = $Symbol;
19060 $Short=~s/\@.+//g;
19061 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019062 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019063 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19064 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019065 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019066 if($IsNeededLib)
19067 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019068 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019069 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019070 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19071 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019072 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019073 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019074 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019075 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019076 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19077 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19078 if($Vers)
19079 {
19080 if($LIB_EXT eq "so")
19081 { # value
19082 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19083 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19084 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019085 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019086 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19087 {
19088 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19089 setLanguage($LibVersion, "C++");
19090 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019091 }
19092 if($CheckObjectsOnly
19093 and $LibVersion==1) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019094 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019095 }
19096 }
19097 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019098 elsif($LIB_TYPE eq "dynamic")
19099 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019100 if($Deps)
19101 {
19102 if(/NEEDED.+\[([^\[\]]+)\]/)
19103 { # dependencies:
19104 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19105 $NeededLib{$1} = 1;
19106 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019107 }
19108 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019109 }
19110 close(LIB);
19111 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019112 if($Vers)
19113 {
19114 if(not $IsNeededLib and $LIB_EXT eq "so")
19115 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019116 my %Found = ();
19117
19118 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019119 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019120 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019121 next if(index($Symbol,"\@")==-1);
19122 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019123 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019124 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019125 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019126 if($Symbol_SameValue ne $Symbol
19127 and index($Symbol_SameValue,"\@")==-1)
19128 {
19129 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019130 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019131 last;
19132 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019133 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019134 }
19135 }
19136
19137 # default
19138 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19139 {
19140 next if(defined $Found{$Symbol});
19141 next if(index($Symbol,"\@\@")==-1);
19142
19143 if($Symbol=~/\A([^\@]*)\@\@/
19144 and not $SymVer{$LibVersion}{$1})
19145 {
19146 $SymVer{$LibVersion}{$1} = $Symbol;
19147 $Found{$Symbol} = 1;
19148 }
19149 }
19150
19151 # non-default
19152 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19153 {
19154 next if(defined $Found{$Symbol});
19155 next if(index($Symbol,"\@")==-1);
19156
19157 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19158 and not $SymVer{$LibVersion}{$1})
19159 {
19160 $SymVer{$LibVersion}{$1} = $Symbol;
19161 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019162 }
19163 }
19164 }
19165 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019166 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019167 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019168 foreach my $DyLib (sort keys(%NeededLib))
19169 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019170 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19171
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019172 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19173 {
19174 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19175 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19176 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019177 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019178 }
19179 }
19180 pop(@RecurLib);
19181 return $Library_Symbol{$LibVersion};
19182}
19183
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019184sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019185{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019186 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019187 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019188 return keys(%Prefixes);
19189}
19190
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019191sub get_prefixes_I($$)
19192{
19193 foreach my $P (@{$_[0]})
19194 {
19195 my @Parts = reverse(split(/[\/\\]+/, $P));
19196 my $Name = $Parts[0];
19197 foreach (1 .. $#Parts)
19198 {
19199 $_[1]->{$Name}{$P} = 1;
19200 last if($_>4 or $Parts[$_] eq "include");
19201 $Name = $Parts[$_].$SLASH.$Name;
19202 }
19203 }
19204}
19205
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019206sub detectSystemHeaders()
19207{
19208 my @SysHeaders = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019209 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019210 {
19211 next if(not -d $DevelPath);
19212 # search for all header files in the /usr/include
19213 # with or without extension (ncurses.h, QtCore, ...)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019214 push(@SysHeaders, cmd_find($DevelPath,"f"));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019215 foreach my $Link (cmd_find($DevelPath,"l"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019216 { # add symbolic links
19217 if(-f $Link) {
19218 push(@SysHeaders, $Link);
19219 }
19220 }
19221 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019222 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019223 { # search for config headers in the /usr/lib
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019224 next if(not -d $DevelPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019225 foreach (cmd_find($DevelPath,"f",'\.h(pp|xx)?\Z|\/include\/',"",1))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019226 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019227 if(/\/(gcc|jvm|syslinux|kbd|parrot|xemacs)/)
19228 { # skip useless headers
19229 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019230 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019231 push(@SysHeaders, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019232 }
19233 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019234 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019235}
19236
19237sub detectSystemObjects()
19238{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019239 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019240 {
19241 next if(not -d $DevelPath);
19242 foreach my $Path (find_libs($DevelPath,"",""))
19243 { # search for shared libraries in the /usr/lib (including symbolic links)
19244 $SystemObjects{parse_libname(get_filename($Path), "name+ext", $OStarget)}{$Path}=1;
19245 }
19246 }
19247}
19248
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019249sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019250{
19251 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019252 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019253 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19254 {
19255 if(not -e $Dest) {
19256 exitStatus("Access_Error", "can't access \'$Dest\'");
19257 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019258 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019259 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19260 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019261 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019262 }
19263 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019264 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019265}
19266
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019267sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019268{
19269 my ($Path, $LibVersion) = @_;
19270 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019271 my $Name = get_filename($Path);
19272 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019273 return 1;
19274 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019275 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019276 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19277 return 1;
19278 }
19279 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19280 {
19281 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19282 return 1;
19283 }
19284 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019285 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019286 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019287 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019288 return 1;
19289 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019290 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019291 return 1;
19292 }
19293 }
19294 return 0;
19295}
19296
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019297sub specificHeader($$)
19298{
19299 my ($Header, $Spec) = @_;
19300 my $Name = get_filename($Header);
19301
19302 if($Spec eq "windows")
19303 {# MS Windows
19304 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19305 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19306 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19307 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19308 my @Dirs = (
19309 "win32",
19310 "win64",
19311 "win",
19312 "windows",
19313 "msvcrt"
19314 ); # /gsf-win32/
19315 if(my $DIRs = join("|", @Dirs)) {
19316 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19317 }
19318 }
19319 elsif($Spec eq "macos")
19320 { # Mac OS
19321 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19322 }
19323
19324 return 0;
19325}
19326
19327sub skipAlienHeader($)
19328{
19329 my $Path = $_[0];
19330 my $Name = get_filename($Path);
19331 my $Dir = get_dirname($Path);
19332
19333 if($Tolerance=~/2/)
19334 { # 2 - skip internal headers
19335 my @Terms = (
19336 "p",
19337 "priv",
19338 "int",
19339 "impl",
19340 "implementation",
19341 "internal",
19342 "private",
19343 "old",
19344 "compat",
19345 "debug",
19346 "test",
19347 "gen"
19348 );
19349
19350 my @Dirs = (
19351 "private",
19352 "priv",
19353 "port",
19354 "impl",
19355 "internal",
19356 "detail",
19357 "details",
19358 "old",
19359 "compat",
19360 "debug",
19361 "config",
19362 "compiler",
19363 "platform",
19364 "test"
19365 );
19366
19367 if(my $TERMs = join("|", @Terms)) {
19368 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19369 }
19370 if(my $DIRs = join("|", @Dirs)) {
19371 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19372 }
19373
19374 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19375 }
19376
19377 if($Tolerance=~/1/)
19378 { # 1 - skip non-Linux headers
19379 if($OSgroup ne "windows")
19380 {
19381 if(specificHeader($Path, "windows")) {
19382 return 1;
19383 }
19384 }
19385 if($OSgroup ne "macos")
19386 {
19387 if(specificHeader($Path, "macos")) {
19388 return 1;
19389 }
19390 }
19391 }
19392
19393 # valid
19394 return 0;
19395}
19396
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019397sub skipHeader($$)
19398{
19399 my ($Path, $LibVersion) = @_;
19400 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019401 if(defined $Cache{"skipHeader"}{$Path}) {
19402 return $Cache{"skipHeader"}{$Path};
19403 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019404 if(defined $Tolerance and $Tolerance=~/1|2/)
19405 { # --tolerant
19406 if(skipAlienHeader($Path)) {
19407 return ($Cache{"skipHeader"}{$Path} = 1);
19408 }
19409 }
19410 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19411 return 0;
19412 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019413 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19414}
19415
19416sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019417{ # returns:
19418 # 1 - if header should NOT be included and checked
19419 # 2 - if header should NOT be included, but should be checked
19420 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019421 my $Name = get_filename($Path);
19422 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019423 return $Kind;
19424 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019425 foreach my $D (keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019426 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019427 if(index($Path, $D)!=-1)
19428 {
19429 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19430 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19431 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019432 }
19433 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019434 foreach my $P (keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019435 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019436 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19437 {
19438 if($Name=~/$P/) {
19439 return $Kind;
19440 }
19441 if($P=~/[\/\\]/ and $Path=~/$P/) {
19442 return $Kind;
19443 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019444 }
19445 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019446
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019447 return 0;
19448}
19449
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019450sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019451{
19452 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019453 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019454 { # system directory
19455 return;
19456 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019457 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019458 { # already registered
19459 return;
19460 }
19461 foreach my $Path (find_libs($Dir,"",1))
19462 {
19463 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019464 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019465 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019466 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019467 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19468}
19469
19470sub registerObject($$)
19471{
19472 my ($Path, $LibVersion) = @_;
19473 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019474 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019475 if($OSgroup=~/linux|bsd/i)
19476 {
19477 if(my $SONAME = getSONAME($Path)) {
19478 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19479 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019480 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019481 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19482 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019483 }
19484}
19485
19486sub getSONAME($)
19487{
19488 my $Path = $_[0];
19489 return if(not $Path);
19490 if(defined $Cache{"getSONAME"}{$Path}) {
19491 return $Cache{"getSONAME"}{$Path};
19492 }
19493 my $ObjdumpCmd = get_CmdPath("objdump");
19494 if(not $ObjdumpCmd) {
19495 exitStatus("Not_Found", "can't find \"objdump\"");
19496 }
19497 my $SonameCmd = "$ObjdumpCmd -x $Path 2>$TMP_DIR/null";
19498 if($OSgroup eq "windows") {
19499 $SonameCmd .= " | find \"SONAME\"";
19500 }
19501 else {
19502 $SonameCmd .= " | grep SONAME";
19503 }
19504 if(my $SonameInfo = `$SonameCmd`) {
19505 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19506 return ($Cache{"getSONAME"}{$Path} = $1);
19507 }
19508 }
19509 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019510}
19511
19512sub getSOPaths_Dest($$)
19513{
19514 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019515 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019516 return ();
19517 }
19518 if(-f $Dest)
19519 {
19520 if(not parse_libname($Dest, "name", $OStarget)) {
19521 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19522 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019523 registerObject($Dest, $LibVersion);
19524 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019525 return ($Dest);
19526 }
19527 elsif(-d $Dest)
19528 {
19529 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019530 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019531 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019532 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19533 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019534 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019535 { # all files and symlinks that match the name of a library
19536 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19537 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019538 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019539 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019540 }
19541 }
19542 }
19543 else
19544 { # search for all files and symlinks
19545 foreach my $Path (find_libs($Dest,"",""))
19546 {
19547 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019548 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019549 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019550 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019551 }
19552 if($OSgroup eq "macos")
19553 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019554 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019555 {
19556 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019557 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019558 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019559 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19560 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019561 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019562 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019563 }
19564 }
19565 }
19566 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019567 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019568 }
19569 else {
19570 return ();
19571 }
19572}
19573
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019574sub isCyclical($$)
19575{
19576 my ($Stack, $Value) = @_;
19577 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019578}
19579
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019580sub detectWordSize()
19581{
19582 return "" if(not $GCC_PATH);
19583 if($Cache{"detectWordSize"}) {
19584 return $Cache{"detectWordSize"};
19585 }
19586 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019587 my $Defines = `$GCC_PATH -E -dD \"$TMP_DIR/empty.h\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019588 unlink("$TMP_DIR/empty.h");
19589 my $WSize = 0;
19590 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019591 { # GCC 4
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019592 $WSize = $1;
19593 }
19594 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019595 { # GCC 3
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019596 my $PTRDIFF = $1;
19597 if($PTRDIFF=~/long/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019598 $WSize = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019599 }
19600 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019601 $WSize = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019602 }
19603 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019604 if(not $WSize) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019605 exitStatus("Error", "can't check WORD size");
19606 }
19607 return ($Cache{"detectWordSize"} = $WSize);
19608}
19609
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019610sub getWordSize($) {
19611 return $WORD_SIZE{$_[0]};
19612}
19613
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019614sub majorVersion($)
19615{
19616 my $V = $_[0];
19617 return 0 if(not $V);
19618 my @VParts = split(/\./, $V);
19619 return $VParts[0];
19620}
19621
19622sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019623{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019624 my ($V1, $V2) = @_;
19625 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019626 my @V1Parts = split(/\./, $V1);
19627 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019628 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
19629 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019630 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
19631 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
19632 }
19633 return -1 if($#V1Parts < $#V2Parts);
19634 return 1 if($#V1Parts > $#V2Parts);
19635 return 0;
19636}
19637
19638sub read_ABI_Dump($$)
19639{
19640 my ($LibVersion, $Path) = @_;
19641 return if(not $LibVersion or not -e $Path);
19642 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019643 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019644 { # input *.abi
19645 $FilePath = $Path;
19646 }
19647 else
19648 { # input *.abi.tar.gz
19649 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019650 if(not isDump_U($FilePath)) {
19651 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19652 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019653 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019654
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019655 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019656
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019657 my $Line = readLineNum($FilePath, 0);
19658 if($Line=~/xml/)
19659 { # XML format
19660 loadModule("XmlDump");
19661 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019662 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019663 else
19664 { # Perl Data::Dumper format (default)
19665 open(DUMP, $FilePath);
19666 local $/ = undef;
19667 my $Content = <DUMP>;
19668 close(DUMP);
19669
19670 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
19671 { # remove temp file
19672 unlink($FilePath);
19673 }
19674 if($Content!~/};\s*\Z/) {
19675 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19676 }
19677 $ABI = eval($Content);
19678 if(not $ABI) {
19679 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
19680 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019681 }
19682 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019683 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019684 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019685 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019686 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019687 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019688 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019689 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019690
19691 if($ABI->{"ABI_DUMP_VERSION"})
19692 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019693 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019694 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019695 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019696 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019697 }
19698 else
19699 { # support for old ABI dumps
19700 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019701 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019702 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019703 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019704 }
19705 if(majorVersion($DVersion)<2)
19706 { # support for old ABI dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019707 if($UseOldDumps)
19708 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019709 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)<0) {
19710 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (older than $OLDEST_SUPPORTED_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019711 }
19712 }
19713 else
19714 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019715 my $Msg = "incompatible version \'$DVersion\' of specified ABI dump (allowed only 2.0<=V<=$ABI_DUMP_VERSION)";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019716 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)>=0) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019717 $Msg .= "\nUse -old-dumps option to use old-version dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019718 }
19719 exitStatus("Dump_Version", $Msg);
19720 }
19721 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019722
19723 if(defined $ABI->{"ABI_DUMPER_VERSION"})
19724 { # DWARF ABI Dump
19725 $UseConv_Real{$LibVersion}{"P"} = 1;
19726 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19727
19728 $UsedDump{$LibVersion}{"DWARF"} = 1;
19729
19730 $TargetComponent = "module";
19731 }
19732
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019733 if(not checkDump($LibVersion, "2.11"))
19734 { # old ABI dumps
19735 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019736 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019737 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019738 { # ABI dump created with --binary option
19739 $UsedDump{$LibVersion}{"BinOnly"} = 1;
19740 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019741 else
19742 { # default
19743 $UsedDump{$LibVersion}{"SrcBin"} = 1;
19744 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019745
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019746 if(defined $ABI->{"Mode"}
19747 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019748 { # --ext option
19749 $ExtendedCheck = 1;
19750 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019751 if($ABI->{"Extra"}) {
19752 $ExtraDump = 1;
19753 }
19754
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019755 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019756 {
19757 $UsedDump{$LibVersion}{"L"} = $Lang;
19758 setLanguage($LibVersion, $Lang);
19759 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019760 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019761 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019762 }
19763 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019764 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019765 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019766 if(not $TInfo)
19767 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019768 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019769 }
19770 my %Tid_TDid = ();
19771 foreach my $TDid (keys(%{$TInfo}))
19772 {
19773 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
19774 {
19775 $MAX_ID = $Tid if($Tid>$MAX_ID);
19776 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019777 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019778 }
19779 }
19780 my %NewID = ();
19781 foreach my $Tid (keys(%Tid_TDid))
19782 {
19783 my @TDids = keys(%{$Tid_TDid{$Tid}});
19784 if($#TDids>=1)
19785 {
19786 foreach my $TDid (@TDids)
19787 {
19788 if($TDid) {
19789 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19790 }
19791 else
19792 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019793 my $ID = ++$MAX_ID;
19794
19795 $NewID{$TDid}{$Tid} = $ID;
19796 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
19797 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019798 }
19799 }
19800 }
19801 else
19802 {
19803 my $TDid = $TDids[0];
19804 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19805 }
19806 }
19807 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
19808 {
19809 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
19810 if(defined $Info{"BaseType"})
19811 {
19812 my $Bid = $Info{"BaseType"}{"Tid"};
19813 my $BDid = $Info{"BaseType"}{"TDid"};
19814 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019815 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019816 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
19817 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
19818 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019819 }
19820 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
19821 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019822 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019823 read_Machine_DumpInfo($ABI, $LibVersion);
19824 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019825 if(not $SymbolInfo{$LibVersion})
19826 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019827 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019828 }
19829 if(not keys(%{$SymbolInfo{$LibVersion}}))
19830 { # validation of old-version dumps
19831 if(not $ExtendedCheck) {
19832 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
19833 }
19834 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019835 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019836 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019837 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019838 else
19839 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019840 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019841 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019842 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019843 }
19844 if(not $DepSymbols)
19845 { # Cannot reconstruct DepSymbols. This may result in false
19846 # positives if the old dump is for library 2. Not a problem if
19847 # old dumps are only from old libraries.
19848 $DepSymbols = {};
19849 }
19850 foreach my $Symbol (keys(%{$DepSymbols})) {
19851 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
19852 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019853 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019854 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
19855 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
19856 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019857 if(not $SkipTypes{$LibVersion})
19858 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019859 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019860 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019861 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019862 if(not $SkipSymbols{$LibVersion})
19863 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019864 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019865 }
19866 if(not $SkipSymbols{$LibVersion})
19867 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019868 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019869 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019870 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
19871 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
19872 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019873 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019874 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019875 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019876 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019877 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019878 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019879 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019880 if(not checkDump($LibVersion, "2.10.1")
19881 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019882 { # support for old ABI dumps: added target headers
19883 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040019884 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019885 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019886 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040019887 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019888 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019889 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019890 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019891 if(defined $ABI->{"GccConstants"})
19892 { # 3.0
19893 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
19894 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
19895 }
19896 }
19897
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019898 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019899 if(not $NestedNameSpaces{$LibVersion})
19900 { # support for old dumps
19901 # Cannot reconstruct NameSpaces. This may affect design
19902 # of the compatibility report.
19903 $NestedNameSpaces{$LibVersion} = {};
19904 }
19905 # target system type
19906 # needed to adopt HTML report
19907 if(not $DumpSystem)
19908 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019909 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019910 }
19911 # recreate environment
19912 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
19913 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019914 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019915 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019916 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19917 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019918 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019919 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019920 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019921 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19922 {
19923 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19924 setLanguage($LibVersion, "C++");
19925 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019926 }
19927 }
19928 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019929 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
19930 {
19931 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
19932 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19933 }
19934 }
19935
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019936 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019937 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019938 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019939 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019940 {
19941 if(not $Symbol_Library{$LibVersion}{$MnglName}
19942 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
19943 push(@VFunc, $MnglName);
19944 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019945 }
19946 }
19947 translateSymbols(@VFunc, $LibVersion);
19948 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019949 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
19950
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019951 if(not checkDump($LibVersion, "3.0"))
19952 { # support for old ABI dumps
19953 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
19954 {
19955 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
19956 {
19957 if(ref($BaseType) eq "HASH") {
19958 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
19959 }
19960 }
19961 }
19962 }
19963
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019964 if(not checkDump($LibVersion, "3.2"))
19965 { # support for old ABI dumps
19966 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
19967 {
19968 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
19969 {
19970 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
19971 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
19972 }
19973 }
19974 }
19975
19976 # repair target headers list
19977 delete($TargetHeaders{$LibVersion});
19978 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040019979 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
19980 }
19981 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
19982 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019983 }
19984
19985 # non-target constants from anon enums
19986 foreach my $Name (keys(%{$Constants{$LibVersion}}))
19987 {
19988 if(not $ExtraDump
19989 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
19990 {
19991 delete($Constants{$LibVersion}{$Name});
19992 }
19993 }
19994 }
19995
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019996 if(not checkDump($LibVersion, "2.20"))
19997 { # support for old ABI dumps
19998 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
19999 {
20000 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20001
20002 if($TType=~/Struct|Union|Enum|Typedef/)
20003 { # repair complex types first
20004 next;
20005 }
20006
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020007 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020008 {
20009 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20010 if($BType=~/Struct|Union|Enum/i)
20011 {
20012 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20013 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20014 }
20015 }
20016 }
20017 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20018 {
20019 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20020 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20021 if($TType=~/Struct|Union|Enum/) {
20022 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20023 }
20024 }
20025 }
20026
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020027 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020028 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020029 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20030 { # support for old ABI dumps < 2.0 (ACC 1.22)
20031 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20032 {
20033 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20034 {
20035 if($Access ne "public") {
20036 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20037 }
20038 }
20039 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20040 }
20041 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20042 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020043 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20044 { # support for old ABI dumps
20045 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20046 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020047 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20048 { # DWARF ABI Dumps
20049 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20050 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020051 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20052 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20053 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020054 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20055 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020056 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020057 foreach (keys(%{$TInfo{"Base"}})) {
20058 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020059 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020060 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020061 if($TInfo{"Type"} eq "MethodPtr")
20062 {
20063 if(defined $TInfo{"Param"})
20064 { # support for old ABI dumps <= 1.17
20065 if(not defined $TInfo{"Param"}{"0"})
20066 {
20067 my $Max = keys(%{$TInfo{"Param"}});
20068 foreach my $Pos (1 .. $Max) {
20069 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20070 }
20071 delete($TInfo{"Param"}{$Max});
20072 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20073 }
20074 }
20075 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020076 if($TInfo{"BaseType"} eq $TypeId)
20077 { # fix ABI dump
20078 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20079 }
20080 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020081 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020082 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020083 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020084 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20085 if(not $BName)
20086 { # broken type
20087 next;
20088 }
20089 if($TInfo{"Name"} eq $BName)
20090 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020091 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020092 next;
20093 }
20094 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20095 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020096 }
20097 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020098 }
20099 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20100 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020101 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020102 }
20103 }
20104
20105 if(not checkDump($LibVersion, "2.15"))
20106 { # support for old ABI dumps
20107 my %Dups = ();
20108 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20109 {
20110 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020111 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020112 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20113 { # remove template decls
20114 delete($SymbolInfo{$LibVersion}{$InfoId});
20115 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020116 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020117 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020118 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20119 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020120 { # templates
20121 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020122 }
20123 }
20124 }
20125
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020126 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20127 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020128 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20129 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20130 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20131 { # support for old ABI dumps (< 3.1)
20132 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20133 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20134 { # add "this" first parameter
20135 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20136 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20137
20138 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20139 {
20140 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20141 foreach my $Pos (reverse(0 .. $#Pos)) {
20142 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20143 }
20144 }
20145 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20146 }
20147 }
20148
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020149 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20150 { # ABI dumps have no mangled names for C-functions
20151 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20152 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020153 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20154 { # support for old ABI dumps
20155 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20156 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020157 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20158 { # DWARF ABI Dumps
20159 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20160 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020161 }
20162
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020163 $Descriptor{$LibVersion}{"Dump"} = 1;
20164}
20165
20166sub read_Machine_DumpInfo($$)
20167{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020168 my ($ABI, $LibVersion) = @_;
20169 if($ABI->{"Arch"}) {
20170 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020171 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020172 if($ABI->{"WordSize"}) {
20173 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020174 }
20175 else
20176 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020177 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020178 }
20179 if(not $WORD_SIZE{$LibVersion})
20180 { # support for old dumps (<1.23)
20181 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20182 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020183 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020184 }
20185 else
20186 {
20187 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020188 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020189 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020190 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20191 { # any "pointer"-type
20192 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020193 last;
20194 }
20195 }
20196 if($PSize)
20197 { # a pointer type size
20198 $WORD_SIZE{$LibVersion} = $PSize;
20199 }
20200 else {
20201 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20202 }
20203 }
20204 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020205 if($ABI->{"GccVersion"}) {
20206 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020207 }
20208}
20209
20210sub read_Libs_DumpInfo($$)
20211{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020212 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020213 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20214 if(not $Library_Symbol{$LibVersion})
20215 { # support for old dumps
20216 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20217 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020218 if(keys(%{$Library_Symbol{$LibVersion}})
20219 and not $DumpAPI) {
20220 $Descriptor{$LibVersion}{"Libs"} = "OK";
20221 }
20222}
20223
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020224sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020225{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020226 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020227
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020228 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020229 and not $DumpAPI) {
20230 $Descriptor{$LibVersion}{"Headers"} = "OK";
20231 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020232 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020233 { # headers info is stored in the old dumps in the different way
20234 if($UseOldDumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020235 and my $Name = $ABI->{"Headers"}{$Identity}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020236 { # support for old dumps: headers info corrected in 1.22
20237 $Identity = $Name;
20238 }
20239 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020240 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020241 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020242
20243 if(keys(%{$ABI->{"Sources"}})
20244 and not $DumpAPI) {
20245 $Descriptor{$LibVersion}{"Sources"} = "OK";
20246 }
20247 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
20248 { # headers info is stored in the old dumps in the different way
20249 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20250 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20251 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020252}
20253
20254sub find_libs($$$)
20255{
20256 my ($Path, $Type, $MaxDepth) = @_;
20257 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020258 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020259}
20260
20261sub createDescriptor($$)
20262{
20263 my ($LibVersion, $Path) = @_;
20264 if(not $LibVersion or not $Path
20265 or not -e $Path) {
20266 return "";
20267 }
20268 if(-d $Path)
20269 { # directory with headers files and shared objects
20270 return "
20271 <version>
20272 ".$TargetVersion{$LibVersion}."
20273 </version>
20274
20275 <headers>
20276 $Path
20277 </headers>
20278
20279 <libs>
20280 $Path
20281 </libs>";
20282 }
20283 else
20284 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020285 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020286 { # standard XML-descriptor
20287 return readFile($Path);
20288 }
20289 elsif(is_header($Path, 2, $LibVersion))
20290 { # header file
20291 return "
20292 <version>
20293 ".$TargetVersion{$LibVersion}."
20294 </version>
20295
20296 <headers>
20297 $Path
20298 </headers>
20299
20300 <libs>
20301 none
20302 </libs>";
20303 }
20304 elsif(parse_libname($Path, "name", $OStarget))
20305 { # shared object
20306 return "
20307 <version>
20308 ".$TargetVersion{$LibVersion}."
20309 </version>
20310
20311 <headers>
20312 none
20313 </headers>
20314
20315 <libs>
20316 $Path
20317 </libs>";
20318 }
20319 else
20320 { # standard XML-descriptor
20321 return readFile($Path);
20322 }
20323 }
20324}
20325
20326sub detect_lib_default_paths()
20327{
20328 my %LPaths = ();
20329 if($OSgroup eq "bsd")
20330 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020331 if(my $LdConfig = get_CmdPath("ldconfig"))
20332 {
20333 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20334 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020335 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20336 {
20337 my $Name = "lib".$1;
20338 if(not defined $LPaths{$Name}) {
20339 $LPaths{$Name} = $2;
20340 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020341 }
20342 }
20343 }
20344 else {
20345 printMsg("WARNING", "can't find ldconfig");
20346 }
20347 }
20348 else
20349 {
20350 if(my $LdConfig = get_CmdPath("ldconfig"))
20351 {
20352 if($SystemRoot and $OSgroup eq "linux")
20353 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20354 if(-e $SystemRoot."/etc/ld.so.conf") {
20355 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20356 }
20357 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020358 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20359 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020360 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20361 {
20362 my ($Name, $Path) = ($1, $2);
20363 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020364 if(not defined $LPaths{$Name})
20365 { # get first element from the list of available paths
20366
20367 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20368 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20369 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20370
20371 $LPaths{$Name} = $Path;
20372 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020373 }
20374 }
20375 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020376 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020377 printMsg("WARNING", "can't find ldconfig");
20378 }
20379 }
20380 return \%LPaths;
20381}
20382
20383sub detect_bin_default_paths()
20384{
20385 my $EnvPaths = $ENV{"PATH"};
20386 if($OSgroup eq "beos") {
20387 $EnvPaths.=":".$ENV{"BETOOLS"};
20388 }
20389 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020390 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020391 {
20392 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020393 next if(not $Path);
20394 if($SystemRoot
20395 and $Path=~/\A\Q$SystemRoot\E\//)
20396 { # do NOT use binaries from target system
20397 next;
20398 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020399 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020400 }
20401}
20402
20403sub detect_inc_default_paths()
20404{
20405 return () if(not $GCC_PATH);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020406 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020407 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020408 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020409 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020410 next if(index($Line, "/cc1plus ")!=-1);
20411
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020412 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20413 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020414 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020415 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020416 if(index($Path, "c++")!=-1
20417 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020418 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020419 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020420 if(not defined $MAIN_CPP_DIR
20421 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20422 $MAIN_CPP_DIR = $Path;
20423 }
20424 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020425 elsif(index($Path, "gcc")!=-1) {
20426 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020427 }
20428 else
20429 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020430 if($Path=~/local[\/\\]+include/)
20431 { # local paths
20432 next;
20433 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020434 if($SystemRoot
20435 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20436 { # The GCC include path for user headers is not a part of the system root
20437 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20438 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20439 next;
20440 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020441 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020442 }
20443 }
20444 }
20445 unlink("$TMP_DIR/empty.h");
20446 return %DPaths;
20447}
20448
20449sub detect_default_paths($)
20450{
20451 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20452 my $Search = $_[0];
20453 if($Search!~/inc/) {
20454 $HSearch = 0;
20455 }
20456 if($Search!~/lib/) {
20457 $LSearch = 0;
20458 }
20459 if($Search!~/bin/) {
20460 $BSearch = 0;
20461 }
20462 if($Search!~/gcc/) {
20463 $GSearch = 0;
20464 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020465 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020466 { # <search_headers> section of the XML descriptor
20467 # do NOT search for systems headers
20468 $HSearch = 0;
20469 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020470 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020471 { # <search_headers> section of the XML descriptor
20472 # do NOT search for systems headers
20473 $LSearch = 0;
20474 }
20475 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20476 { # additional search paths
20477 next if($Type eq "include" and not $HSearch);
20478 next if($Type eq "lib" and not $LSearch);
20479 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020480 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020481 }
20482 if($OSgroup ne "windows")
20483 { # unix-like
20484 foreach my $Type ("include", "lib", "bin")
20485 { # automatic detection of system "devel" directories
20486 next if($Type eq "include" and not $HSearch);
20487 next if($Type eq "lib" and not $LSearch);
20488 next if($Type eq "bin" and not $BSearch);
20489 my ($UsrDir, $RootDir) = ("/usr", "/");
20490 if($SystemRoot and $Type ne "bin")
20491 { # 1. search for target headers and libraries
20492 # 2. use host commands: ldconfig, readelf, etc.
20493 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20494 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020495 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020496 if(-d $RootDir."/".$Type)
20497 { # if "/lib" is symbolic link
20498 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020499 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020500 }
20501 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020502 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020503 }
20504 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020505 if(-d $UsrDir)
20506 {
20507 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020508 if(-d $UsrDir."/".$Type)
20509 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020510 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020511 }
20512 }
20513 }
20514 }
20515 if($BSearch)
20516 {
20517 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020518 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020519 }
20520 # check environment variables
20521 if($OSgroup eq "beos")
20522 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020523 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020524 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020525 if($_ eq ".") {
20526 next;
20527 }
20528 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20529 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20530 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020531 }
20532 }
20533 if($HSearch)
20534 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020535 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20536 split(/:|;/, $ENV{"BEINCLUDES"})
20537 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020538 }
20539 if($LSearch)
20540 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020541 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20542 split(/:|;/, $ENV{"BELIBRARIES"}),
20543 split(/:|;/, $ENV{"LIBRARY_PATH"})
20544 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020545 }
20546 }
20547 if($LSearch)
20548 { # using linker to get system paths
20549 if(my $LPaths = detect_lib_default_paths())
20550 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020551 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020552 foreach my $Name (keys(%{$LPaths}))
20553 {
20554 if($SystemRoot
20555 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20556 { # wrong ldconfig configuration
20557 # check your <sysroot>/etc/ld.so.conf
20558 next;
20559 }
20560 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020561 if(my $Dir = get_dirname($LPaths->{$Name})) {
20562 $Dirs{$Dir} = 1;
20563 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020564 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020565 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020566 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020567 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020568 }
20569 if($BSearch)
20570 {
20571 if($CrossGcc)
20572 { # --cross-gcc=arm-linux-gcc
20573 if(-e $CrossGcc)
20574 { # absolute or relative path
20575 $GCC_PATH = get_abs_path($CrossGcc);
20576 }
20577 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20578 { # command name
20579 $GCC_PATH = $CrossGcc;
20580 }
20581 else {
20582 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20583 }
20584 if($GCC_PATH=~/\s/) {
20585 $GCC_PATH = "\"".$GCC_PATH."\"";
20586 }
20587 }
20588 }
20589 if($GSearch)
20590 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020591 if(not $CrossGcc)
20592 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020593 $GCC_PATH = get_CmdPath("gcc");
20594 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020595 if(not $GCC_PATH)
20596 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020597 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020598 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020599 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020600 { # select the latest version
20601 @GCCs = sort {$b cmp $a} @GCCs;
20602 if(check_gcc($GCCs[0], "3"))
20603 {
20604 $GCC_PATH = $GCCs[0];
20605 last;
20606 }
20607 }
20608 }
20609 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020610 if(not $GCC_PATH) {
20611 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
20612 }
20613 if(not $CheckObjectsOnly_Opt)
20614 {
20615 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
20616 {
20617 my $GccTarget = get_dumpmachine($GCC_PATH);
20618 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget)");
20619 if($GccTarget=~/symbian/)
20620 {
20621 $OStarget = "symbian";
20622 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
20623 }
20624 }
20625 else {
20626 exitStatus("Error", "something is going wrong with the GCC compiler");
20627 }
20628 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020629 if($HSearch)
20630 {
20631 if(not $NoStdInc)
20632 { # do NOT search in GCC standard paths
20633 my %DPaths = detect_inc_default_paths();
20634 @DefaultCppPaths = @{$DPaths{"Cpp"}};
20635 @DefaultGccPaths = @{$DPaths{"Gcc"}};
20636 @DefaultIncPaths = @{$DPaths{"Inc"}};
20637 push_U($SystemPaths{"include"}, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020638 }
20639 }
20640 }
20641 if($HSearch)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020642 { # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020643 my $IncPath = "/usr/include";
20644 if($SystemRoot) {
20645 $IncPath = $SystemRoot.$IncPath;
20646 }
20647 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020648 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020649 }
20650 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020651
20652 if($ExtraInfo)
20653 {
20654 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
20655 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
20656 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020657}
20658
20659sub getLIB_EXT($)
20660{
20661 my $Target = $_[0];
20662 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
20663 return $Ext;
20664 }
20665 return $OS_LibExt{$LIB_TYPE}{"default"};
20666}
20667
20668sub getAR_EXT($)
20669{
20670 my $Target = $_[0];
20671 if(my $Ext = $OS_Archive{$Target}) {
20672 return $Ext;
20673 }
20674 return $OS_Archive{"default"};
20675}
20676
20677sub get_dumpversion($)
20678{
20679 my $Cmd = $_[0];
20680 return "" if(not $Cmd);
20681 if($Cache{"get_dumpversion"}{$Cmd}) {
20682 return $Cache{"get_dumpversion"}{$Cmd};
20683 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020684 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020685 chomp($V);
20686 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
20687}
20688
20689sub get_dumpmachine($)
20690{
20691 my $Cmd = $_[0];
20692 return "" if(not $Cmd);
20693 if($Cache{"get_dumpmachine"}{$Cmd}) {
20694 return $Cache{"get_dumpmachine"}{$Cmd};
20695 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020696 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020697 chomp($Machine);
20698 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
20699}
20700
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020701sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020702{
20703 my $Cmd = $_[0];
20704 return "" if(not $Cmd);
20705 my @Options = (
20706 "--version",
20707 "-help"
20708 );
20709 foreach my $Opt (@Options)
20710 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020711 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020712 if($Info) {
20713 return 1;
20714 }
20715 }
20716 return 0;
20717}
20718
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020719sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020720{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020721 my ($Cmd, $ReqVer) = @_;
20722 return 0 if(not $Cmd or not $ReqVer);
20723 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
20724 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020725 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020726 if(my $GccVer = get_dumpversion($Cmd))
20727 {
20728 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
20729 if(cmpVersions($GccVer, $ReqVer)>=0) {
20730 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
20731 }
20732 }
20733 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020734}
20735
20736sub get_depth($)
20737{
20738 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020739 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020740 }
20741 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
20742}
20743
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020744sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020745{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020746 return if($Cache{"registerGccHeaders"}); # this function should be called once
20747
20748 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020749 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020750 my @Headers = cmd_find($Path,"f");
20751 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20752 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020753 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020754 my $FileName = get_filename($HPath);
20755 if(not defined $DefaultGccHeader{$FileName})
20756 { # skip duplicated
20757 $DefaultGccHeader{$FileName} = $HPath;
20758 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020759 }
20760 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020761 $Cache{"registerGccHeaders"} = 1;
20762}
20763
20764sub registerCppHeaders()
20765{
20766 return if($Cache{"registerCppHeaders"}); # this function should be called once
20767
20768 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020769 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020770 my @Headers = cmd_find($CppDir,"f");
20771 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20772 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020773 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020774 my $FileName = get_filename($Path);
20775 if(not defined $DefaultCppHeader{$FileName})
20776 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020777 $DefaultCppHeader{$FileName} = $Path;
20778 }
20779 }
20780 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020781 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020782}
20783
20784sub parse_libname($$$)
20785{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020786 return "" if(not $_[0]);
20787 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
20788 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020789 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020790 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
20791}
20792
20793sub parse_libname_I($$$)
20794{
20795 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020796
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020797 if($Target eq "symbian") {
20798 return parse_libname_symbian($Name, $Type);
20799 }
20800 elsif($Target eq "windows") {
20801 return parse_libname_windows($Name, $Type);
20802 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020803
20804 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020805 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020806 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020807 { # libSDL-1.2.so.0.7.1
20808 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020809 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020810 if($Type eq "name")
20811 { # libSDL-1.2
20812 # libwbxml2
20813 return $2;
20814 }
20815 elsif($Type eq "name+ext")
20816 { # libSDL-1.2.so
20817 # libwbxml2.so
20818 return $1;
20819 }
20820 elsif($Type eq "version")
20821 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020822 if(defined $7
20823 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020824 { # 0.7.1
20825 return $7;
20826 }
20827 else
20828 { # libc-2.5.so (=>2.5 version)
20829 my $MV = $5;
20830 $MV=~s/\A[\-\_]+//g;
20831 return $MV;
20832 }
20833 }
20834 elsif($Type eq "short")
20835 { # libSDL
20836 # libwbxml2
20837 return $3;
20838 }
20839 elsif($Type eq "shortest")
20840 { # SDL
20841 # wbxml
20842 return shortest_name($3);
20843 }
20844 }
20845 return "";# error
20846}
20847
20848sub parse_libname_symbian($$)
20849{
20850 my ($Name, $Type) = @_;
20851 my $Ext = getLIB_EXT("symbian");
20852 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
20853 { # libpthread{00010001}.dso
20854 if($Type eq "name")
20855 { # libpthread{00010001}
20856 return $2;
20857 }
20858 elsif($Type eq "name+ext")
20859 { # libpthread{00010001}.dso
20860 return $1;
20861 }
20862 elsif($Type eq "version")
20863 { # 00010001
20864 my $V = $4;
20865 $V=~s/\{(.+)\}/$1/;
20866 return $V;
20867 }
20868 elsif($Type eq "short")
20869 { # libpthread
20870 return $3;
20871 }
20872 elsif($Type eq "shortest")
20873 { # pthread
20874 return shortest_name($3);
20875 }
20876 }
20877 return "";# error
20878}
20879
20880sub parse_libname_windows($$)
20881{
20882 my ($Name, $Type) = @_;
20883 my $Ext = getLIB_EXT("windows");
20884 if($Name=~/((.+?)\.$Ext)\Z/)
20885 { # netapi32.dll
20886 if($Type eq "name")
20887 { # netapi32
20888 return $2;
20889 }
20890 elsif($Type eq "name+ext")
20891 { # netapi32.dll
20892 return $1;
20893 }
20894 elsif($Type eq "version")
20895 { # DLL version embedded
20896 # at binary-level
20897 return "";
20898 }
20899 elsif($Type eq "short")
20900 { # netapi32
20901 return $2;
20902 }
20903 elsif($Type eq "shortest")
20904 { # netapi
20905 return shortest_name($2);
20906 }
20907 }
20908 return "";# error
20909}
20910
20911sub shortest_name($)
20912{
20913 my $Name = $_[0];
20914 # remove prefix
20915 $Name=~s/\A(lib|open)//;
20916 # remove suffix
20917 $Name=~s/[\W\d_]+\Z//i;
20918 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
20919 return $Name;
20920}
20921
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020922sub createSymbolsList($$$$$)
20923{
20924 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
20925 read_ABI_Dump(1, $DPath);
20926 if(not $CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020927 prepareSymbols(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020928 }
20929 my %SymbolHeaderLib = ();
20930 my $Total = 0;
20931 # Get List
20932 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
20933 {
20934 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020935 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020936 next;
20937 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020938 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020939 { # skip other symbols
20940 next;
20941 }
20942 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
20943 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020944 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020945 next;
20946 }
20947 my $DyLib = $Symbol_Library{1}{$Symbol};
20948 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020949 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020950 next;
20951 }
20952 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
20953 $Total+=1;
20954 }
20955 # Draw List
20956 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
20957 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
20958 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
20959 {
20960 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
20961 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020962 my %NS_Symbol = ();
20963 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020964 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020965 }
20966 foreach my $NameSpace (sort keys(%NS_Symbol))
20967 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020968 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020969 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
20970 foreach my $Symbol (@SortedInterfaces)
20971 {
20972 my $SubReport = "";
20973 my $Signature = get_Signature($Symbol, 1);
20974 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020975 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020976 }
20977 if($Symbol=~/\A(_Z|\?)/)
20978 {
20979 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020980 $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 +040020981 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020982 else {
20983 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
20984 }
20985 }
20986 else
20987 {
20988 if($Signature) {
20989 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
20990 }
20991 else {
20992 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
20993 }
20994 }
20995 $SYMBOLS_LIST .= $SubReport;
20996 }
20997 }
20998 $SYMBOLS_LIST .= "<br/>\n";
20999 }
21000 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021001 # clear info
21002 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21003 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21004 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21005 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021006 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021007 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021008 my $CssStyles = readModule("Styles", "SymbolsList.css");
21009 my $JScripts = readModule("Scripts", "Sections.js");
21010 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021011 my $Title = "$LName: public symbols";
21012 my $Keywords = "$LName, API, symbols";
21013 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021014 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021015 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021016 <br/><br/><hr/>\n".getReportFooter($LName, 1)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021017 <div style='height:999px;'></div></body></html>";
21018 writeFile($SaveTo, $SYMBOLS_LIST);
21019}
21020
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021021sub add_target_libs($)
21022{
21023 foreach (@{$_[0]}) {
21024 $TargetLibs{$_} = 1;
21025 }
21026}
21027
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021028sub is_target_lib($)
21029{
21030 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021031 if(not $LName) {
21032 return 0;
21033 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021034 if($TargetLibraryName
21035 and $LName!~/\Q$TargetLibraryName\E/) {
21036 return 0;
21037 }
21038 if(keys(%TargetLibs)
21039 and not $TargetLibs{$LName}
21040 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21041 return 0;
21042 }
21043 return 1;
21044}
21045
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021046sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021047{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021048 my ($H, $V) = @_;
21049 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021050 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021051 if($TargetHeaders{$V}{$H}) {
21052 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021053 }
21054 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021055 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021056}
21057
21058sub checkVersionNum($$)
21059{
21060 my ($LibVersion, $Path) = @_;
21061 if(my $VerNum = $TargetVersion{$LibVersion}) {
21062 return $VerNum;
21063 }
21064 my $UsedAltDescr = 0;
21065 foreach my $Part (split(/\s*,\s*/, $Path))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021066 { # try to get version string from file path
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021067 next if(isDump($Part)); # ABI dump
21068 next if($Part=~/\.(xml|desc)\Z/i); # XML descriptor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021069 my $VerNum = "";
21070 if(parse_libname($Part, "name", $OStarget))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021071 {
21072 $UsedAltDescr = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021073 $VerNum = parse_libname($Part, "version", $OStarget);
21074 if(not $VerNum) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021075 $VerNum = readStrVer($Part);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021076 }
21077 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021078 elsif(is_header($Part, 2, $LibVersion) or -d $Part)
21079 {
21080 $UsedAltDescr = 1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021081 $VerNum = readStrVer($Part);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021082 }
21083 if($VerNum ne "")
21084 {
21085 $TargetVersion{$LibVersion} = $VerNum;
21086 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021087 printMsg("WARNING", "setting version number to $VerNum (use -vnum option to change it)");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021088 }
21089 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021090 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 +040021091 }
21092 return $TargetVersion{$LibVersion};
21093 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021094 }
21095 if($UsedAltDescr)
21096 {
21097 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021098 exitStatus("Error", "version number is not set (use -vnum option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021099 }
21100 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021101 exitStatus("Error", ($LibVersion==1?"1st":"2nd")." version number is not set (use -v$LibVersion option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021102 }
21103 }
21104}
21105
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021106sub readStrVer($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021107{
21108 my $Str = $_[0];
21109 return "" if(not $Str);
21110 $Str=~s/\Q$TargetLibraryName\E//g;
21111 if($Str=~/(\/|\\|\w|\A)[\-\_]*(\d+[\d\.\-]+\d+|\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021112 { # .../libssh-0.4.0/...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021113 return $2;
21114 }
21115 elsif(my $V = parse_libname($Str, "version", $OStarget)) {
21116 return $V;
21117 }
21118 return "";
21119}
21120
21121sub readLibs($)
21122{
21123 my $LibVersion = $_[0];
21124 if($OStarget eq "windows")
21125 { # dumpbin.exe will crash
21126 # without VS Environment
21127 check_win32_env();
21128 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021129 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021130 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021131 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021132}
21133
21134sub dump_sorting($)
21135{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021136 my $Hash = $_[0];
21137 return [] if(not $Hash);
21138 my @Keys = keys(%{$Hash});
21139 return [] if($#Keys<0);
21140 if($Keys[0]=~/\A\d+\Z/)
21141 { # numbers
21142 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021143 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021144 else
21145 { # strings
21146 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021147 }
21148}
21149
21150sub printMsg($$)
21151{
21152 my ($Type, $Msg) = @_;
21153 if($Type!~/\AINFO/) {
21154 $Msg = $Type.": ".$Msg;
21155 }
21156 if($Type!~/_C\Z/) {
21157 $Msg .= "\n";
21158 }
21159 if($Quiet)
21160 { # --quiet option
21161 appendFile($COMMON_LOG_PATH, $Msg);
21162 }
21163 else
21164 {
21165 if($Type eq "ERROR") {
21166 print STDERR $Msg;
21167 }
21168 else {
21169 print $Msg;
21170 }
21171 }
21172}
21173
21174sub exitStatus($$)
21175{
21176 my ($Code, $Msg) = @_;
21177 printMsg("ERROR", $Msg);
21178 exit($ERROR_CODE{$Code});
21179}
21180
21181sub exitReport()
21182{ # the tool has run without any errors
21183 printReport();
21184 if($COMPILE_ERRORS)
21185 { # errors in headers may add false positives/negatives
21186 exit($ERROR_CODE{"Compile_Error"});
21187 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021188 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21189 { # --binary
21190 exit($ERROR_CODE{"Incompatible"});
21191 }
21192 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21193 { # --source
21194 exit($ERROR_CODE{"Incompatible"});
21195 }
21196 elsif($RESULT{"Source"}{"Problems"}
21197 or $RESULT{"Binary"}{"Problems"})
21198 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021199 exit($ERROR_CODE{"Incompatible"});
21200 }
21201 else {
21202 exit($ERROR_CODE{"Compatible"});
21203 }
21204}
21205
21206sub readRules($)
21207{
21208 my $Kind = $_[0];
21209 if(not -f $RULES_PATH{$Kind}) {
21210 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21211 }
21212 my $Content = readFile($RULES_PATH{$Kind});
21213 while(my $Rule = parseTag(\$Content, "rule"))
21214 {
21215 my $RId = parseTag(\$Rule, "id");
21216 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21217 foreach my $Prop (@Properties) {
21218 if(my $Value = parseTag(\$Rule, lc($Prop)))
21219 {
21220 $Value=~s/\n[ ]*//;
21221 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21222 }
21223 }
21224 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21225 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21226 }
21227 else {
21228 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21229 }
21230 }
21231}
21232
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021233sub getReportPath($)
21234{
21235 my $Level = $_[0];
21236 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21237 if($Level eq "Binary")
21238 {
21239 if($BinaryReportPath)
21240 { # --bin-report-path
21241 return $BinaryReportPath;
21242 }
21243 elsif($OutputReportPath)
21244 { # --report-path
21245 return $OutputReportPath;
21246 }
21247 else
21248 { # default
21249 return $Dir."/abi_compat_report.$ReportFormat";
21250 }
21251 }
21252 elsif($Level eq "Source")
21253 {
21254 if($SourceReportPath)
21255 { # --src-report-path
21256 return $SourceReportPath;
21257 }
21258 elsif($OutputReportPath)
21259 { # --report-path
21260 return $OutputReportPath;
21261 }
21262 else
21263 { # default
21264 return $Dir."/src_compat_report.$ReportFormat";
21265 }
21266 }
21267 else
21268 {
21269 if($OutputReportPath)
21270 { # --report-path
21271 return $OutputReportPath;
21272 }
21273 else
21274 { # default
21275 return $Dir."/compat_report.$ReportFormat";
21276 }
21277 }
21278}
21279
21280sub printStatMsg($)
21281{
21282 my $Level = $_[0];
21283 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21284}
21285
21286sub listAffected($)
21287{
21288 my $Level = $_[0];
21289 my $List = "";
21290 foreach (keys(%{$TotalAffected{$Level}}))
21291 {
21292 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21293 { # skip "Low"-severity problems
21294 next;
21295 }
21296 $List .= "$_\n";
21297 }
21298 my $Dir = get_dirname(getReportPath($Level));
21299 if($Level eq "Binary") {
21300 writeFile($Dir."/abi_affected.txt", $List);
21301 }
21302 elsif($Level eq "Source") {
21303 writeFile($Dir."/src_affected.txt", $List);
21304 }
21305}
21306
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021307sub printReport()
21308{
21309 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021310 createReport();
21311 if($JoinReport or $DoubleReport)
21312 {
21313 if($RESULT{"Binary"}{"Problems"}
21314 or $RESULT{"Source"}{"Problems"}) {
21315 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021316 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021317 else {
21318 printMsg("INFO", "result: COMPATIBLE");
21319 }
21320 printStatMsg("Binary");
21321 printStatMsg("Source");
21322 if($ListAffected)
21323 { # --list-affected
21324 listAffected("Binary");
21325 listAffected("Source");
21326 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021327 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021328 elsif($BinaryOnly)
21329 {
21330 if($RESULT{"Binary"}{"Problems"}) {
21331 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21332 }
21333 else {
21334 printMsg("INFO", "result: COMPATIBLE");
21335 }
21336 printStatMsg("Binary");
21337 if($ListAffected)
21338 { # --list-affected
21339 listAffected("Binary");
21340 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021341 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021342 elsif($SourceOnly)
21343 {
21344 if($RESULT{"Source"}{"Problems"}) {
21345 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21346 }
21347 else {
21348 printMsg("INFO", "result: COMPATIBLE");
21349 }
21350 printStatMsg("Source");
21351 if($ListAffected)
21352 { # --list-affected
21353 listAffected("Source");
21354 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021355 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021356 if($StdOut)
21357 {
21358 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021359 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021360 printMsg("INFO", "compatibility report has been generated to stdout");
21361 }
21362 else
21363 { # default
21364 printMsg("INFO", "compatibility reports have been generated to stdout");
21365 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021366 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021367 else
21368 {
21369 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021370 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021371 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21372 }
21373 elsif($DoubleReport)
21374 { # default
21375 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21376 }
21377 elsif($BinaryOnly)
21378 { # --binary
21379 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21380 }
21381 elsif($SourceOnly)
21382 { # --source
21383 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21384 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021385 }
21386}
21387
21388sub check_win32_env()
21389{
21390 if(not $ENV{"DevEnvDir"}
21391 or not $ENV{"LIB"}) {
21392 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21393 }
21394}
21395
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021396sub diffSets($$)
21397{
21398 my ($S1, $S2) = @_;
21399 my @SK1 = keys(%{$S1});
21400 my @SK2 = keys(%{$S2});
21401 if($#SK1!=$#SK2) {
21402 return 1;
21403 }
21404 foreach my $K1 (@SK1)
21405 {
21406 if(not defined $S2->{$K1}) {
21407 return 1;
21408 }
21409 }
21410 return 0;
21411}
21412
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021413sub create_ABI_Dump()
21414{
21415 if(not -e $DumpAPI) {
21416 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21417 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021418 my @DParts = split(/\s*,\s*/, $DumpAPI);
21419 foreach my $Part (@DParts)
21420 {
21421 if(not -e $Part) {
21422 exitStatus("Access_Error", "can't access \'$Part\'");
21423 }
21424 }
21425 checkVersionNum(1, $DumpAPI);
21426 foreach my $Part (@DParts)
21427 {
21428 if(isDump($Part)) {
21429 read_ABI_Dump(1, $Part);
21430 }
21431 else {
21432 readDescriptor(1, createDescriptor(1, $Part));
21433 }
21434 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021435
21436 if(not $Descriptor{1}{"Version"})
21437 { # set to default: X
21438 $Descriptor{1}{"Version"} = "X";
21439 }
21440
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021441 initLogging(1);
21442 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021443
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021444 my $DumpPath = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi";
21445 $DumpPath .= ".".$AR_EXT; # gzipped by default
21446 if($OutputDumpPath)
21447 { # user defined path
21448 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021449 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021450 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21451
21452 if(not $Archive and not $StdOut)
21453 { # check archive utilities
21454 if($OSgroup eq "windows")
21455 { # using zip
21456 my $ZipCmd = get_CmdPath("zip");
21457 if(not $ZipCmd) {
21458 exitStatus("Not_Found", "can't find \"zip\"");
21459 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021460 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021461 else
21462 { # using tar and gzip
21463 my $TarCmd = get_CmdPath("tar");
21464 if(not $TarCmd) {
21465 exitStatus("Not_Found", "can't find \"tar\"");
21466 }
21467 my $GzipCmd = get_CmdPath("gzip");
21468 if(not $GzipCmd) {
21469 exitStatus("Not_Found", "can't find \"gzip\"");
21470 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021471 }
21472 }
21473
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021474 if(not $Descriptor{1}{"Dump"})
21475 {
21476 if(not $CheckHeadersOnly) {
21477 readLibs(1);
21478 }
21479 if($CheckHeadersOnly) {
21480 setLanguage(1, "C++");
21481 }
21482 if(not $CheckObjectsOnly) {
21483 searchForHeaders(1);
21484 }
21485 $WORD_SIZE{1} = detectWordSize();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021486 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021487 if(not $Descriptor{1}{"Dump"})
21488 {
21489 if($Descriptor{1}{"Headers"}) {
21490 readHeaders(1);
21491 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021492 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021493 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021494 if(not keys(%{$SymbolInfo{1}}))
21495 { # check if created dump is valid
21496 if(not $ExtendedCheck and not $CheckObjectsOnly)
21497 {
21498 if($CheckHeadersOnly) {
21499 exitStatus("Empty_Set", "the set of public symbols is empty");
21500 }
21501 else {
21502 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21503 }
21504 }
21505 }
21506 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021507 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021508 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21509 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021510 if($ExtraDump)
21511 { # add unmangled names to the ABI dump
21512 my @Names = ();
21513 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21514 {
21515 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21516 push(@Names, $MnglName);
21517 }
21518 }
21519 translateSymbols(@Names, 1);
21520 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21521 {
21522 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21523 {
21524 if(my $Unmangled = $tr_name{$MnglName})
21525 {
21526 if($MnglName ne $Unmangled) {
21527 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21528 }
21529 }
21530 }
21531 }
21532 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021533
21534 my %GccConstants = (); # built-in GCC constants
21535 foreach my $Name (keys(%{$Constants{1}}))
21536 {
21537 if(not defined $Constants{1}{$Name}{"Header"})
21538 {
21539 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21540 delete($Constants{1}{$Name});
21541 }
21542 }
21543
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021544 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021545 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021546 "TypeInfo" => $TypeInfo{1},
21547 "SymbolInfo" => $SymbolInfo{1},
21548 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021549 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021550 "SymbolVersion" => $SymVer{1},
21551 "LibraryVersion" => $Descriptor{1}{"Version"},
21552 "LibraryName" => $TargetLibraryName,
21553 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021554 "SkipTypes" => $SkipTypes{1},
21555 "SkipSymbols" => $SkipSymbols{1},
21556 "SkipNameSpaces" => $SkipNameSpaces{1},
21557 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021558 "Headers" => \%HeadersInfo,
21559 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021560 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021561 "NameSpaces" => $NestedNameSpaces{1},
21562 "Target" => $OStarget,
21563 "Arch" => getArch(1),
21564 "WordSize" => $WORD_SIZE{1},
21565 "GccVersion" => get_dumpversion($GCC_PATH),
21566 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21567 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21568 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021569 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021570 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021571 }
21572 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021573 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021574 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021575 if($ExtendedCheck)
21576 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021577 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021578 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021579 if($BinaryOnly)
21580 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021581 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021582 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021583 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021584 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021585 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021586 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21587 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021588 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021589
21590 my $ABI_DUMP = "";
21591 if($UseXML)
21592 {
21593 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021594 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021595 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021596 else
21597 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021598 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021599 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021600 if($StdOut)
21601 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021602 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021603 printMsg("INFO", "ABI dump has been generated to stdout");
21604 return;
21605 }
21606 else
21607 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021608 my ($DDir, $DName) = separate_path($DumpPath);
21609 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021610 if(not $Archive) {
21611 $DPath = $DumpPath;
21612 }
21613
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021614 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021615
21616 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021617 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021618 close(DUMP);
21619
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021620 if(not -s $DPath) {
21621 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21622 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021623 if($Archive) {
21624 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021625 }
21626
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021627 if($OutputDumpPath) {
21628 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021629 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021630 else {
21631 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
21632 }
21633 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 +040021634 }
21635}
21636
21637sub quickEmptyReports()
21638{ # Quick "empty" reports
21639 # 4 times faster than merging equal dumps
21640 # NOTE: the dump contains the "LibraryVersion" attribute
21641 # if you change the version, then your dump will be different
21642 # OVERCOME: use -v1 and v2 options for comparing dumps
21643 # and don't change version in the XML descriptor (and dumps)
21644 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
21645 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
21646 {
21647 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
21648 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
21649 if($FilePath1 and $FilePath2)
21650 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021651 my $Line = readLineNum($FilePath1, 0);
21652 if($Line=~/xml/)
21653 { # XML format
21654 # is not supported yet
21655 return;
21656 }
21657
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021658 local $/ = undef;
21659
21660 open(DUMP1, $FilePath1);
21661 my $Content1 = <DUMP1>;
21662 close(DUMP1);
21663
21664 open(DUMP2, $FilePath2);
21665 my $Content2 = <DUMP2>;
21666 close(DUMP2);
21667
21668 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021669 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021670 # clean memory
21671 undef $Content2;
21672
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021673 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021674 my $ABIdump = eval($Content1);
21675
21676 # clean memory
21677 undef $Content1;
21678
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021679 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021680 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 +040021681 }
21682 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021683 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021684 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
21685 }
21686 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021687 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021688 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
21689 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021690 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021691 read_Libs_DumpInfo($ABIdump, 1);
21692 read_Machine_DumpInfo($ABIdump, 1);
21693 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021694
21695 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
21696 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
21697
21698 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
21699 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
21700
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021701 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
21702 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
21703 exitReport();
21704 }
21705 }
21706 }
21707}
21708
21709sub initLogging($)
21710{
21711 my $LibVersion = $_[0];
21712 # create log directory
21713 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
21714 if($OutputLogPath{$LibVersion})
21715 { # user-defined by -log-path option
21716 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
21717 }
21718 if($LogMode ne "n") {
21719 mkpath($LOG_DIR);
21720 }
21721 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021722 if($Debug)
21723 { # debug directory
21724 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021725
21726 if(not $ExtraInfo)
21727 { # enable --extra-info
21728 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
21729 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021730 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021731 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021732}
21733
21734sub writeLog($$)
21735{
21736 my ($LibVersion, $Msg) = @_;
21737 if($LogMode ne "n") {
21738 appendFile($LOG_PATH{$LibVersion}, $Msg);
21739 }
21740}
21741
21742sub resetLogging($)
21743{
21744 my $LibVersion = $_[0];
21745 if($LogMode!~/a|n/)
21746 { # remove old log
21747 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021748 if($Debug) {
21749 rmtree($DEBUG_PATH{$LibVersion});
21750 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021751 }
21752}
21753
21754sub printErrorLog($)
21755{
21756 my $LibVersion = $_[0];
21757 if($LogMode ne "n") {
21758 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
21759 }
21760}
21761
21762sub isDump($)
21763{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021764 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz|\.zip|\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021765 return $1;
21766 }
21767 return 0;
21768}
21769
21770sub isDump_U($)
21771{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021772 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021773 return $1;
21774 }
21775 return 0;
21776}
21777
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021778sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021779{
21780 # read input XML descriptors or ABI dumps
21781 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021782 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021783 }
21784 my @DParts1 = split(/\s*,\s*/, $Descriptor{1}{"Path"});
21785 foreach my $Part (@DParts1)
21786 {
21787 if(not -e $Part) {
21788 exitStatus("Access_Error", "can't access \'$Part\'");
21789 }
21790 }
21791 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021792 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021793 }
21794 my @DParts2 = split(/\s*,\s*/, $Descriptor{2}{"Path"});
21795 foreach my $Part (@DParts2)
21796 {
21797 if(not -e $Part) {
21798 exitStatus("Access_Error", "can't access \'$Part\'");
21799 }
21800 }
21801 detect_default_paths("bin"); # to extract dumps
21802 if($#DParts1==0 and $#DParts2==0
21803 and isDump($Descriptor{1}{"Path"})
21804 and isDump($Descriptor{2}{"Path"}))
21805 { # optimization: equal ABI dumps
21806 quickEmptyReports();
21807 }
21808 checkVersionNum(1, $Descriptor{1}{"Path"});
21809 checkVersionNum(2, $Descriptor{2}{"Path"});
21810 printMsg("INFO", "preparation, please wait ...");
21811 foreach my $Part (@DParts1)
21812 {
21813 if(isDump($Part)) {
21814 read_ABI_Dump(1, $Part);
21815 }
21816 else {
21817 readDescriptor(1, createDescriptor(1, $Part));
21818 }
21819 }
21820 foreach my $Part (@DParts2)
21821 {
21822 if(isDump($Part)) {
21823 read_ABI_Dump(2, $Part);
21824 }
21825 else {
21826 readDescriptor(2, createDescriptor(2, $Part));
21827 }
21828 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021829
21830 if(not $Descriptor{1}{"Version"})
21831 { # set to default: X
21832 $Descriptor{1}{"Version"} = "X";
21833 }
21834
21835 if(not $Descriptor{2}{"Version"})
21836 { # set to default: Y
21837 $Descriptor{2}{"Version"} = "Y";
21838 }
21839
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021840 initLogging(1);
21841 initLogging(2);
21842 # check consistency
21843 if(not $Descriptor{1}{"Headers"}
21844 and not $Descriptor{1}{"Libs"}) {
21845 exitStatus("Error", "descriptor d1 does not contain both header files and libraries info");
21846 }
21847 if(not $Descriptor{2}{"Headers"}
21848 and not $Descriptor{2}{"Libs"}) {
21849 exitStatus("Error", "descriptor d2 does not contain both header files and libraries info");
21850 }
21851 if($Descriptor{1}{"Headers"} and not $Descriptor{1}{"Libs"}
21852 and not $Descriptor{2}{"Headers"} and $Descriptor{2}{"Libs"}) {
21853 exitStatus("Error", "can't compare headers with $SLIB_TYPE libraries");
21854 }
21855 elsif(not $Descriptor{1}{"Headers"} and $Descriptor{1}{"Libs"}
21856 and $Descriptor{2}{"Headers"} and not $Descriptor{2}{"Libs"}) {
21857 exitStatus("Error", "can't compare $SLIB_TYPE libraries with headers");
21858 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021859 if(not $Descriptor{1}{"Headers"})
21860 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021861 if($CheckHeadersOnly_Opt) {
21862 exitStatus("Error", "can't find header files info in descriptor d1");
21863 }
21864 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021865 if(not $Descriptor{2}{"Headers"})
21866 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021867 if($CheckHeadersOnly_Opt) {
21868 exitStatus("Error", "can't find header files info in descriptor d2");
21869 }
21870 }
21871 if(not $Descriptor{1}{"Headers"}
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021872 or not $Descriptor{2}{"Headers"})
21873 {
21874 if(not $CheckObjectsOnly_Opt)
21875 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021876 printMsg("WARNING", "comparing $SLIB_TYPE libraries only");
21877 $CheckObjectsOnly = 1;
21878 }
21879 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021880 if(not $Descriptor{1}{"Libs"})
21881 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021882 if($CheckObjectsOnly_Opt) {
21883 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d1");
21884 }
21885 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021886 if(not $Descriptor{2}{"Libs"})
21887 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021888 if($CheckObjectsOnly_Opt) {
21889 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d2");
21890 }
21891 }
21892 if(not $Descriptor{1}{"Libs"}
21893 or not $Descriptor{2}{"Libs"})
21894 { # comparing standalone header files
21895 # comparing ABI dumps created with --headers-only
21896 if(not $CheckHeadersOnly_Opt)
21897 {
21898 printMsg("WARNING", "checking headers only");
21899 $CheckHeadersOnly = 1;
21900 }
21901 }
21902 if($UseDumps)
21903 { # --use-dumps
21904 # parallel processing
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021905 my $DumpPath1 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi.$AR_EXT";
21906 my $DumpPath2 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{2}{"Version"}.".abi.$AR_EXT";
21907
21908 unlink($DumpPath1);
21909 unlink($DumpPath2);
21910
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021911 my $pid = fork();
21912 if($pid)
21913 { # dump on two CPU cores
21914 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
21915 if($RelativeDirectory{1}) {
21916 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
21917 }
21918 if($OutputLogPath{1}) {
21919 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
21920 }
21921 if($CrossGcc) {
21922 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
21923 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021924 if($Quiet)
21925 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021926 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021927 @PARAMS = (@PARAMS, "-logging-mode", "a");
21928 }
21929 elsif($LogMode and $LogMode ne "w")
21930 { # "w" is default
21931 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021932 }
21933 if($ExtendedCheck) {
21934 @PARAMS = (@PARAMS, "-extended");
21935 }
21936 if($UserLang) {
21937 @PARAMS = (@PARAMS, "-lang", $UserLang);
21938 }
21939 if($TargetVersion{1}) {
21940 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
21941 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021942 if($BinaryOnly) {
21943 @PARAMS = (@PARAMS, "-binary");
21944 }
21945 if($SourceOnly) {
21946 @PARAMS = (@PARAMS, "-source");
21947 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021948 if($SortDump) {
21949 @PARAMS = (@PARAMS, "-sort");
21950 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021951 if($DumpFormat and $DumpFormat ne "perl") {
21952 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
21953 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021954 if($CheckHeadersOnly) {
21955 @PARAMS = (@PARAMS, "-headers-only");
21956 }
21957 if($CheckObjectsOnly) {
21958 @PARAMS = (@PARAMS, "-objects-only");
21959 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021960 if($Debug)
21961 {
21962 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021963 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021964 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021965 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021966 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021967 exit(1);
21968 }
21969 }
21970 else
21971 { # child
21972 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
21973 if($RelativeDirectory{2}) {
21974 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
21975 }
21976 if($OutputLogPath{2}) {
21977 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
21978 }
21979 if($CrossGcc) {
21980 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
21981 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021982 if($Quiet)
21983 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021984 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021985 @PARAMS = (@PARAMS, "-logging-mode", "a");
21986 }
21987 elsif($LogMode and $LogMode ne "w")
21988 { # "w" is default
21989 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021990 }
21991 if($ExtendedCheck) {
21992 @PARAMS = (@PARAMS, "-extended");
21993 }
21994 if($UserLang) {
21995 @PARAMS = (@PARAMS, "-lang", $UserLang);
21996 }
21997 if($TargetVersion{2}) {
21998 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
21999 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022000 if($BinaryOnly) {
22001 @PARAMS = (@PARAMS, "-binary");
22002 }
22003 if($SourceOnly) {
22004 @PARAMS = (@PARAMS, "-source");
22005 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022006 if($SortDump) {
22007 @PARAMS = (@PARAMS, "-sort");
22008 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022009 if($DumpFormat and $DumpFormat ne "perl") {
22010 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22011 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022012 if($CheckHeadersOnly) {
22013 @PARAMS = (@PARAMS, "-headers-only");
22014 }
22015 if($CheckObjectsOnly) {
22016 @PARAMS = (@PARAMS, "-objects-only");
22017 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022018 if($Debug)
22019 {
22020 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022021 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022022 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022023 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022024 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022025 exit(1);
22026 }
22027 else {
22028 exit(0);
22029 }
22030 }
22031 waitpid($pid, 0);
22032 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022033 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22034 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022035 if($TargetLibraryFName ne $TargetLibraryName) {
22036 @CMP_PARAMS = (@CMP_PARAMS, "-l-full", $TargetLibraryFName);
22037 }
22038 if($ShowRetVal) {
22039 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22040 }
22041 if($CrossGcc) {
22042 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22043 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022044 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22045 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022046 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022047 }
22048 if($ReportFormat and $ReportFormat ne "html")
22049 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022050 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22051 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022052 if($OutputReportPath) {
22053 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22054 }
22055 if($BinaryReportPath) {
22056 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22057 }
22058 if($SourceReportPath) {
22059 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22060 }
22061 if($LoggingPath) {
22062 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22063 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022064 if($CheckHeadersOnly) {
22065 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22066 }
22067 if($CheckObjectsOnly) {
22068 @CMP_PARAMS = (@CMP_PARAMS, "-objects-only");
22069 }
22070 if($BinaryOnly) {
22071 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22072 }
22073 if($SourceOnly) {
22074 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22075 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022076 if($Browse) {
22077 @CMP_PARAMS = (@CMP_PARAMS, "-browse", $Browse);
22078 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022079 if($OpenReport) {
22080 @CMP_PARAMS = (@CMP_PARAMS, "-open");
22081 }
22082 if($Debug)
22083 {
22084 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22085 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022086 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022087 system("perl", $0, @CMP_PARAMS);
22088 exit($?>>8);
22089 }
22090 if(not $Descriptor{1}{"Dump"}
22091 or not $Descriptor{2}{"Dump"})
22092 { # need GCC toolchain to analyze
22093 # header files and libraries
22094 detect_default_paths("inc|lib|gcc");
22095 }
22096 if(not $Descriptor{1}{"Dump"})
22097 {
22098 if(not $CheckHeadersOnly) {
22099 readLibs(1);
22100 }
22101 if($CheckHeadersOnly) {
22102 setLanguage(1, "C++");
22103 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022104 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022105 searchForHeaders(1);
22106 }
22107 $WORD_SIZE{1} = detectWordSize();
22108 }
22109 if(not $Descriptor{2}{"Dump"})
22110 {
22111 if(not $CheckHeadersOnly) {
22112 readLibs(2);
22113 }
22114 if($CheckHeadersOnly) {
22115 setLanguage(2, "C++");
22116 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022117 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022118 searchForHeaders(2);
22119 }
22120 $WORD_SIZE{2} = detectWordSize();
22121 }
22122 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22123 { # support for old ABI dumps
22124 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022125 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022126 {
22127 $WORD_SIZE{1} = $WORD_SIZE{2};
22128 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22129 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022130 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022131 {
22132 $WORD_SIZE{2} = $WORD_SIZE{1};
22133 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22134 }
22135 }
22136 elsif(not $WORD_SIZE{1}
22137 and not $WORD_SIZE{2})
22138 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022139 $WORD_SIZE{1} = "4";
22140 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022141 }
22142 if($Descriptor{1}{"Dump"})
22143 { # support for old ABI dumps
22144 prepareTypes(1);
22145 }
22146 if($Descriptor{2}{"Dump"})
22147 { # support for old ABI dumps
22148 prepareTypes(2);
22149 }
22150 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22151 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22152 }
22153 # started to process input data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022154 if(not $CheckObjectsOnly)
22155 {
22156 if($Descriptor{1}{"Headers"}
22157 and not $Descriptor{1}{"Dump"}) {
22158 readHeaders(1);
22159 }
22160 if($Descriptor{2}{"Headers"}
22161 and not $Descriptor{2}{"Dump"}) {
22162 readHeaders(2);
22163 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022164 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022165
22166 # clean memory
22167 %SystemHeaders = ();
22168 %mangled_name_gcc = ();
22169
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022170 prepareSymbols(1);
22171 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022172
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022173 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022174 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022175
22176 # Virtual Tables
22177 registerVTable(1);
22178 registerVTable(2);
22179
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022180 if(not checkDump(1, "1.22")
22181 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022182 { # support for old ABI dumps
22183 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22184 {
22185 if($ClassName=~/</)
22186 { # templates
22187 if(not defined $VirtualTable{1}{$ClassName})
22188 { # synchronize
22189 delete($VirtualTable{2}{$ClassName});
22190 }
22191 }
22192 }
22193 }
22194
22195 registerOverriding(1);
22196 registerOverriding(2);
22197
22198 setVirtFuncPositions(1);
22199 setVirtFuncPositions(2);
22200
22201 # Other
22202 addParamNames(1);
22203 addParamNames(2);
22204
22205 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022206}
22207
22208sub compareAPIs($)
22209{
22210 my $Level = $_[0];
22211 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022212 loadModule("CallConv");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022213 if($Level eq "Binary") {
22214 printMsg("INFO", "comparing ABIs ...");
22215 }
22216 else {
22217 printMsg("INFO", "comparing APIs ...");
22218 }
22219 if($CheckHeadersOnly
22220 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022221 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022222 detectAdded_H($Level);
22223 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022224 }
22225 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022226 { # added/removed in libs
22227 detectAdded($Level);
22228 detectRemoved($Level);
22229 }
22230 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022231 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022232 mergeSymbols($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022233 if(keys(%{$CheckedSymbols{$Level}})) {
22234 mergeConstants($Level);
22235 }
22236 }
22237 if($CheckHeadersOnly
22238 or $Level eq "Source")
22239 { # added/removed in headers
22240 mergeHeaders($Level);
22241 }
22242 else
22243 { # added/removed in libs
22244 mergeLibs($Level);
22245 if($CheckImpl
22246 and $Level eq "Binary") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022247 mergeImpl();
22248 }
22249 }
22250}
22251
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022252sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022253{
22254 my %Opts = (
22255 "OStarget"=>$OStarget,
22256 "Debug"=>$Debug,
22257 "Quiet"=>$Quiet,
22258 "LogMode"=>$LogMode,
22259 "CheckHeadersOnly"=>$CheckHeadersOnly,
22260
22261 "SystemRoot"=>$SystemRoot,
22262 "MODULES_DIR"=>$MODULES_DIR,
22263 "GCC_PATH"=>$GCC_PATH,
22264 "TargetSysInfo"=>$TargetSysInfo,
22265 "CrossPrefix"=>$CrossPrefix,
22266 "TargetLibraryName"=>$TargetLibraryName,
22267 "CrossGcc"=>$CrossGcc,
22268 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022269 "NoStdInc"=>$NoStdInc,
22270
22271 "BinaryOnly" => $BinaryOnly,
22272 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022273 );
22274 return \%Opts;
22275}
22276
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022277sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022278{
22279 my %CODE_ERROR = reverse(%ERROR_CODE);
22280 return $CODE_ERROR{$_[0]};
22281}
22282
22283sub scenario()
22284{
22285 if($StdOut)
22286 { # enable quiet mode
22287 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022288 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022289 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022290 if(not $LogMode)
22291 { # default
22292 $LogMode = "w";
22293 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022294 if($UserLang)
22295 { # --lang=C++
22296 $UserLang = uc($UserLang);
22297 $COMMON_LANGUAGE{1}=$UserLang;
22298 $COMMON_LANGUAGE{2}=$UserLang;
22299 }
22300 if($LoggingPath)
22301 {
22302 $OutputLogPath{1} = $LoggingPath;
22303 $OutputLogPath{2} = $LoggingPath;
22304 if($Quiet) {
22305 $COMMON_LOG_PATH = $LoggingPath;
22306 }
22307 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022308 if($OutputDumpPath)
22309 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022310 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022311 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22312 }
22313 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022314 if($BinaryOnly and $SourceOnly)
22315 { # both --binary and --source
22316 # is the default mode
22317 $DoubleReport = 1;
22318 $JoinReport = 0;
22319 $BinaryOnly = 0;
22320 $SourceOnly = 0;
22321 if($OutputReportPath)
22322 { # --report-path
22323 $DoubleReport = 0;
22324 $JoinReport = 1;
22325 }
22326 }
22327 elsif($BinaryOnly or $SourceOnly)
22328 { # --binary or --source
22329 $DoubleReport = 0;
22330 $JoinReport = 0;
22331 }
22332 if($UseXML)
22333 { # --xml option
22334 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022335 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022337 if($ReportFormat)
22338 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022339 $ReportFormat = lc($ReportFormat);
22340 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022341 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022342 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022343 if($ReportFormat eq "htm")
22344 { # HTM == HTML
22345 $ReportFormat = "html";
22346 }
22347 elsif($ReportFormat eq "xml")
22348 { # --report-format=XML equal to --xml
22349 $UseXML = 1;
22350 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022351 }
22352 else
22353 { # default: HTML
22354 $ReportFormat = "html";
22355 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022356 if($DumpFormat)
22357 { # validate
22358 $DumpFormat = lc($DumpFormat);
22359 if($DumpFormat!~/\A(xml|perl)\Z/) {
22360 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22361 }
22362 if($DumpFormat eq "xml")
22363 { # --dump-format=XML equal to --xml
22364 $UseXML = 1;
22365 }
22366 }
22367 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022368 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022369 $DumpFormat = "perl";
22370 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022371 if($Quiet and $LogMode!~/a|n/)
22372 { # --quiet log
22373 if(-f $COMMON_LOG_PATH) {
22374 unlink($COMMON_LOG_PATH);
22375 }
22376 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022377 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022378 $CheckUndefined = 1;
22379 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022380 if($TestTool and $UseDumps)
22381 { # --test && --use-dumps == --test-dump
22382 $TestDump = 1;
22383 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022384 if($Tolerant)
22385 { # enable all
22386 $Tolerance = 1234;
22387 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022388 if($Help)
22389 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022390 HELP_MESSAGE();
22391 exit(0);
22392 }
22393 if($InfoMsg) {
22394 INFO_MESSAGE();
22395 exit(0);
22396 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022397 if($ShowVersion)
22398 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022399 printMsg("INFO", "ABI Compliance Checker (ACC) $TOOL_VERSION\nCopyright (C) 2012 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.");
22400 exit(0);
22401 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022402 if($DumpVersion)
22403 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022404 printMsg("INFO", $TOOL_VERSION);
22405 exit(0);
22406 }
22407 if($ExtendedCheck) {
22408 $CheckHeadersOnly = 1;
22409 }
22410 if($SystemRoot_Opt)
22411 { # user defined root
22412 if(not -e $SystemRoot_Opt) {
22413 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22414 }
22415 $SystemRoot = $SystemRoot_Opt;
22416 $SystemRoot=~s/[\/]+\Z//g;
22417 if($SystemRoot) {
22418 $SystemRoot = get_abs_path($SystemRoot);
22419 }
22420 }
22421 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022422
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022423 if($SortDump)
22424 {
22425 $Data::Dumper::Useperl = 1;
22426 $Data::Dumper::Sortkeys = \&dump_sorting;
22427 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022428
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022429 if($TargetLibsPath)
22430 {
22431 if(not -f $TargetLibsPath) {
22432 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22433 }
22434 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22435 $TargetLibs{$Lib} = 1;
22436 }
22437 }
22438 if($TargetHeadersPath)
22439 { # --headers-list
22440 if(not -f $TargetHeadersPath) {
22441 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22442 }
22443 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22444 {
22445 $TargetHeaders{1}{$Header} = 1;
22446 $TargetHeaders{2}{$Header} = 1;
22447 }
22448 }
22449 if($TargetHeader)
22450 { # --header
22451 $TargetHeaders{1}{$TargetHeader} = 1;
22452 $TargetHeaders{2}{$TargetHeader} = 1;
22453 }
22454 if($TestTool
22455 or $TestDump)
22456 { # --test, --test-dump
22457 detect_default_paths("bin|gcc"); # to compile libs
22458 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022459 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
22460 $LIB_EXT, $GCC_PATH, $Browse, $OpenReport, $SortDump, $CheckHeadersOnly, $CheckObjectsOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022461 exit(0);
22462 }
22463 if($DumpSystem)
22464 { # --dump-system
22465 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022466 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022467 { # system XML descriptor
22468 if(not -f $DumpSystem) {
22469 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22470 }
22471 my $Ret = readSystemDescriptor(readFile($DumpSystem));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022472 foreach (@{$Ret->{"Tools"}})
22473 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022474 push_U($SystemPaths{"bin"}, $_);
22475 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022476 }
22477 if($Ret->{"CrossPrefix"}) {
22478 $CrossPrefix = $Ret->{"CrossPrefix"};
22479 }
22480 }
22481 elsif($SystemRoot_Opt)
22482 { # -sysroot "/" option
22483 # default target: /usr/lib, /usr/include
22484 # search libs: /usr/lib and /lib
22485 if(not -e $SystemRoot."/usr/lib") {
22486 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22487 }
22488 if(not -e $SystemRoot."/lib") {
22489 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22490 }
22491 if(not -e $SystemRoot."/usr/include") {
22492 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22493 }
22494 readSystemDescriptor("
22495 <name>
22496 $DumpSystem
22497 </name>
22498 <headers>
22499 $SystemRoot/usr/include
22500 </headers>
22501 <libs>
22502 $SystemRoot/usr/lib
22503 </libs>
22504 <search_libs>
22505 $SystemRoot/lib
22506 </search_libs>");
22507 }
22508 else {
22509 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22510 }
22511 detect_default_paths("bin|gcc"); # to check symbols
22512 if($OStarget eq "windows")
22513 { # to run dumpbin.exe
22514 # and undname.exe
22515 check_win32_env();
22516 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022517 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022518 exit(0);
22519 }
22520 if($CmpSystems)
22521 { # --cmp-systems
22522 detect_default_paths("bin"); # to extract dumps
22523 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022524 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022525 exit(0);
22526 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022527 if($GenerateTemplate)
22528 {
22529 writeFile("VERSION.xml", $DescriptorTemplate."\n");
22530 printMsg("INFO", "XML-descriptor template ./VERSION.xml has been generated");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022531 exit(0);
22532 }
22533 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022534 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022535 }
22536 else
22537 { # validate library name
22538 if($TargetLibraryName=~/[\*\/\\]/) {
22539 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22540 }
22541 }
22542 if(not $TargetLibraryFName) {
22543 $TargetLibraryFName = $TargetLibraryName;
22544 }
22545 if($CheckHeadersOnly_Opt and $CheckObjectsOnly_Opt) {
22546 exitStatus("Error", "you can't specify both -headers-only and -objects-only options at the same time");
22547 }
22548 if($SymbolsListPath)
22549 {
22550 if(not -f $SymbolsListPath) {
22551 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22552 }
22553 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22554 $SymbolsList{$Interface} = 1;
22555 }
22556 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022557 if($SkipSymbolsListPath)
22558 {
22559 if(not -f $SkipSymbolsListPath) {
22560 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22561 }
22562 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath))) {
22563 $SkipSymbolsList{$Interface} = 1;
22564 }
22565 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022566 if($SkipHeadersPath)
22567 {
22568 if(not -f $SkipHeadersPath) {
22569 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22570 }
22571 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022572 { # register for both versions
22573 $SkipHeadersList{1}{$Path} = 1;
22574 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022575 my ($CPath, $Type) = classifyPath($Path);
22576 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022577 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022578 }
22579 }
22580 if($ParamNamesPath)
22581 {
22582 if(not -f $ParamNamesPath) {
22583 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22584 }
22585 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22586 {
22587 if($Line=~s/\A(\w+)\;//)
22588 {
22589 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022590 if($Line=~/;(\d+);/)
22591 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022592 while($Line=~s/(\d+);(\w+)//) {
22593 $AddIntParams{$Interface}{$1}=$2;
22594 }
22595 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022596 else
22597 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022598 my $Num = 0;
22599 foreach my $Name (split(/;/, $Line)) {
22600 $AddIntParams{$Interface}{$Num++}=$Name;
22601 }
22602 }
22603 }
22604 }
22605 }
22606 if($AppPath)
22607 {
22608 if(not -f $AppPath) {
22609 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22610 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022611 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022612 $SymbolsList_App{$Interface} = 1;
22613 }
22614 }
22615 if($DumpAPI)
22616 { # --dump-abi
22617 # make an API dump
22618 create_ABI_Dump();
22619 exit($COMPILE_ERRORS);
22620 }
22621 # default: compare APIs
22622 # -d1 <path>
22623 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022624 compareInit();
22625 if($JoinReport or $DoubleReport)
22626 {
22627 compareAPIs("Binary");
22628 compareAPIs("Source");
22629 }
22630 elsif($BinaryOnly) {
22631 compareAPIs("Binary");
22632 }
22633 elsif($SourceOnly) {
22634 compareAPIs("Source");
22635 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022636 exitReport();
22637}
22638
22639scenario();