blob: dd0d5587b1f19daf7ff859f4a26c83c9a6e09653 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04003# ABI Compliance Checker (ACC) 1.99.1
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 Ponomarenkoab282102012-03-11 11:57:02 +040063use Data::Dumper;
Andrey Ponomarenko2fba6302012-03-29 17:44:47 +040064use Config;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040065
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040066my $TOOL_VERSION = "1.99.1";
67my $ABI_DUMP_VERSION = "3.1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040068my $OLDEST_SUPPORTED_VERSION = "1.18";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040069my $XML_REPORT_VERSION = "1.1";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040070my $XML_ABI_DUMP_VERSION = "1.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040071my $OSgroup = get_OSgroup();
72my $ORIG_DIR = cwd();
73my $TMP_DIR = tempdir(CLEANUP=>1);
74
75# Internal modules
76my $MODULES_DIR = get_Modules();
77push(@INC, get_dirname($MODULES_DIR));
78# Rules DB
79my %RULES_PATH = (
80 "Binary" => $MODULES_DIR."/RulesBin.xml",
81 "Source" => $MODULES_DIR."/RulesSrc.xml");
82
83my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName, $GenerateTemplate,
84$TestTool, $DumpAPI, $SymbolsListPath, $CheckHeadersOnly_Opt, $UseDumps,
85$CheckObjectsOnly_Opt, $AppPath, $StrictCompat, $DumpVersion, $ParamNamesPath,
86%RelativeDirectory, $TargetLibraryFName, $TestDump, $CheckImpl, $LoggingPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040087%TargetVersion, $InfoMsg, $UseOldDumps, $CrossGcc, %OutputLogPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040088$OutputReportPath, $OutputDumpPath, $ShowRetVal, $SystemRoot_Opt, $DumpSystem,
89$CmpSystems, $TargetLibsPath, $Debug, $CrossPrefix, $UseStaticLibs, $NoStdInc,
90$TargetComponent_Opt, $TargetSysInfo, $TargetHeader, $ExtendedCheck, $Quiet,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040091$SkipHeadersPath, $CppCompat, $LogMode, $StdOut, $ListAffected, $ReportFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040092$UserLang, $TargetHeadersPath, $BinaryOnly, $SourceOnly, $BinaryReportPath,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040093$SourceReportPath, $UseXML, $Browse, $OpenReport, $SortDump, $DumpFormat,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040094$ExtraInfo, $ExtraDump, $Force, $Tolerance, $Tolerant, $SkipSymbolsListPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040095
96my $CmdName = get_filename($0);
97my %OS_LibExt = (
98 "dynamic" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040099 "linux"=>"so",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400100 "macos"=>"dylib",
101 "windows"=>"dll",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400102 "symbian"=>"dso",
103 "default"=>"so"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400104 },
105 "static" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400106 "linux"=>"a",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400107 "windows"=>"lib",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400108 "symbian"=>"lib",
109 "default"=>"a"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400110 }
111);
112
113my %OS_Archive = (
114 "windows"=>"zip",
115 "default"=>"tar.gz"
116);
117
118my %ERROR_CODE = (
119 # Compatible verdict
120 "Compatible"=>0,
121 "Success"=>0,
122 # Incompatible verdict
123 "Incompatible"=>1,
124 # Undifferentiated error code
125 "Error"=>2,
126 # System command is not found
127 "Not_Found"=>3,
128 # Cannot access input files
129 "Access_Error"=>4,
130 # Cannot compile header files
131 "Cannot_Compile"=>5,
132 # Header compiled with errors
133 "Compile_Error"=>6,
134 # Invalid input ABI dump
135 "Invalid_Dump"=>7,
136 # Incompatible version of ABI dump
137 "Dump_Version"=>8,
138 # Cannot find a module
139 "Module_Error"=>9,
140 # Empty intersection between
141 # headers and shared objects
142 "Empty_Intersection"=>10,
143 # Empty set of symbols in headers
144 "Empty_Set"=>11
145);
146
147my %HomePage = (
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400148 "Wiki"=>"http://ispras.linuxbase.org/index.php/ABI_compliance_checker",
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400149 "Dev1"=>"https://github.com/lvc/abi-compliance-checker",
150 "Dev2"=>"http://forge.ispras.ru/projects/abi-compliance-checker"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400151);
152
153my $ShortUsage = "ABI Compliance Checker (ACC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400154A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400155Copyright (C) 2012 ROSA Laboratory
156License: GNU LGPL or GNU GPL
157
158Usage: $CmdName [options]
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400159Example: $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400160
161OLD.xml and NEW.xml are XML-descriptors:
162
163 <version>
164 1.0
165 </version>
166
167 <headers>
168 /path/to/headers/
169 </headers>
170
171 <libs>
172 /path/to/libraries/
173 </libs>
174
175More info: $CmdName --help\n";
176
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400177if($#ARGV==-1)
178{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400179 printMsg("INFO", $ShortUsage);
180 exit(0);
181}
182
183foreach (2 .. $#ARGV)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400184{ # correct comma separated options
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400185 if($ARGV[$_-1] eq ",")
186 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400187 $ARGV[$_-2].=",".$ARGV[$_];
188 splice(@ARGV, $_-1, 2);
189 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400190 elsif($ARGV[$_-1]=~/,\Z/)
191 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400192 $ARGV[$_-1].=$ARGV[$_];
193 splice(@ARGV, $_, 1);
194 }
195 elsif($ARGV[$_]=~/\A,/
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400196 and $ARGV[$_] ne ",")
197 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400198 $ARGV[$_-1].=$ARGV[$_];
199 splice(@ARGV, $_, 1);
200 }
201}
202
203GetOptions("h|help!" => \$Help,
204 "i|info!" => \$InfoMsg,
205 "v|version!" => \$ShowVersion,
206 "dumpversion!" => \$DumpVersion,
207# general options
208 "l|lib|library=s" => \$TargetLibraryName,
209 "d1|old|o=s" => \$Descriptor{1}{"Path"},
210 "d2|new|n=s" => \$Descriptor{2}{"Path"},
211 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
212 "old-dumps!" => \$UseOldDumps,
213# extra options
214 "d|descriptor-template!" => \$GenerateTemplate,
215 "app|application=s" => \$AppPath,
216 "static-libs!" => \$UseStaticLibs,
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +0400217 "cross-gcc|gcc-path=s" => \$CrossGcc,
218 "cross-prefix|gcc-prefix=s" => \$CrossPrefix,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400219 "sysroot=s" => \$SystemRoot_Opt,
220 "v1|version1|vnum=s" => \$TargetVersion{1},
221 "v2|version2=s" => \$TargetVersion{2},
222 "s|strict!" => \$StrictCompat,
223 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400224 "skip-symbols=s" => \$SkipSymbolsListPath,
225 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400226 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400227 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400228 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
229 "objects-only!" => \$CheckObjectsOnly_Opt,
230 "check-impl|check-implementation!" => \$CheckImpl,
231 "show-retval!" => \$ShowRetVal,
232 "use-dumps!" => \$UseDumps,
233 "nostdinc!" => \$NoStdInc,
234 "dump-system=s" => \$DumpSystem,
235 "sysinfo=s" => \$TargetSysInfo,
236 "cmp-systems!" => \$CmpSystems,
237 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400238 "ext|extended!" => \$ExtendedCheck,
239 "q|quiet!" => \$Quiet,
240 "stdout!" => \$StdOut,
241 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400242 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400243 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400244 "lang=s" => \$UserLang,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400245 "binary|bin|abi!" => \$BinaryOnly,
246 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400247# other options
248 "test!" => \$TestTool,
249 "test-dump!" => \$TestDump,
250 "debug!" => \$Debug,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400251 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400252 "p|params=s" => \$ParamNamesPath,
253 "relpath1|relpath=s" => \$RelativeDirectory{1},
254 "relpath2=s" => \$RelativeDirectory{2},
255 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400256 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400257 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400258 "bin-report-path=s" => \$BinaryReportPath,
259 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400260 "log-path=s" => \$LoggingPath,
261 "log1-path=s" => \$OutputLogPath{1},
262 "log2-path=s" => \$OutputLogPath{2},
263 "logging-mode=s" => \$LogMode,
264 "list-affected!" => \$ListAffected,
265 "l-full|lib-full=s" => \$TargetLibraryFName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400266 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400267 "b|browse=s" => \$Browse,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400268 "open!" => \$OpenReport,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400269 "extra-info=s" => \$ExtraInfo,
270 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400271 "force!" => \$Force,
272 "tolerance=s" => \$Tolerance,
273 "tolerant!" => \$Tolerant
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400274) or ERR_MESSAGE();
275
276sub ERR_MESSAGE()
277{
278 printMsg("INFO", "\n".$ShortUsage);
279 exit($ERROR_CODE{"Error"});
280}
281
282my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
283my $SLIB_TYPE = $LIB_TYPE;
284if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
285{ # show as "shared" library
286 $SLIB_TYPE = "shared";
287}
288my $LIB_EXT = getLIB_EXT($OSgroup);
289my $AR_EXT = getAR_EXT($OSgroup);
290my $BYTE_SIZE = 8;
291my $COMMON_LOG_PATH = "logs/run.log";
292
293my $HelpMessage="
294NAME:
295 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400296 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400297
298DESCRIPTION:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400299 ABI Compliance Checker (ACC) is a tool for checking backward binary and
300 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
301 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
302 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
303 and/or source-level compatibility: changes in calling stack, v-table changes,
304 removed symbols, renamed fields, etc. Binary incompatibility may result in
305 crashing or incorrect behavior of applications built with an old version of
306 a library if they run on a new one. Source incompatibility may result in
307 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400308
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400309 The tool is intended for developers of software libraries and maintainers
310 of operating systems who are interested in ensuring backward compatibility,
311 i.e. allow old applications to run or to be recompiled with newer library
312 versions.
313
314 Also the tool can be used by ISVs for checking applications portability to
315 new library versions. Found issues can be taken into account when adapting
316 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400317
318 This tool is free software: you can redistribute it and/or modify it
319 under the terms of the GNU LGPL or GNU GPL.
320
321USAGE:
322 $CmdName [options]
323
324EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400325 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400326
327 OLD.xml and NEW.xml are XML-descriptors:
328
329 <version>
330 1.0
331 </version>
332
333 <headers>
334 /path1/to/header(s)/
335 /path2/to/header(s)/
336 ...
337 </headers>
338
339 <libs>
340 /path1/to/library(ies)/
341 /path2/to/library(ies)/
342 ...
343 </libs>
344
345INFORMATION OPTIONS:
346 -h|-help
347 Print this help.
348
349 -i|-info
350 Print complete info.
351
352 -v|-version
353 Print version information.
354
355 -dumpversion
356 Print the tool version ($TOOL_VERSION) and don't do anything else.
357
358GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400359 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400360 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400361
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400362 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400363 Descriptor of 1st (old) library version.
364 It may be one of the following:
365
366 1. XML-descriptor (VERSION.xml file):
367
368 <version>
369 1.0
370 </version>
371
372 <headers>
373 /path1/to/header(s)/
374 /path2/to/header(s)/
375 ...
376 </headers>
377
378 <libs>
379 /path1/to/library(ies)/
380 /path2/to/library(ies)/
381 ...
382 </libs>
383
384 ... (XML-descriptor template
385 can be generated by -d option)
386
387 2. ABI dump generated by -dump option
388 3. Directory with headers and/or $SLIB_TYPE libraries
389 4. Single header file
390 5. Single $SLIB_TYPE library
391 6. Comma separated list of headers and/or libraries
392
393 If you are using an 2-6 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400394 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400395
396 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400397 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400398
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400399 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400400 Descriptor of 2nd (new) library version.
401
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400402 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400403 Create library ABI dump for the input XML descriptor. You can
404 transfer it anywhere and pass instead of the descriptor. Also
405 it can be used for debugging the tool.
406
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400407 Supported ABI dump versions: 2.0<=V<=$ABI_DUMP_VERSION
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400408
409 -old-dumps
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400410 Enable support for old-version ABI dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0).\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400411
412sub HELP_MESSAGE() {
413 printMsg("INFO", $HelpMessage."
414MORE INFO:
415 $CmdName --info\n");
416}
417
418sub INFO_MESSAGE()
419{
420 printMsg("INFO", "$HelpMessage
421EXTRA OPTIONS:
422 -d|-descriptor-template
423 Create XML-descriptor template ./VERSION.xml
424
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400425 -app|-application PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400426 This option allows to specify the application that should be checked
427 for portability to the new library version.
428
429 -static-libs
430 Check static libraries instead of the shared ones. The <libs> section
431 of the XML-descriptor should point to static libraries location.
432
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400433 -cross-gcc|-gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400434 Path to the cross GCC compiler to use instead of the usual (host) GCC.
435
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400436 -cross-prefix|-gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400437 GCC toolchain prefix.
438
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400439 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400440 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400441 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400442
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400443 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400444 Specify 1st library version outside the descriptor. This option is needed
445 if you have prefered an alternative descriptor type (see -d1 option).
446
447 In general case you should specify it in the XML-descriptor:
448 <version>
449 VERSION
450 </version>
451
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400452 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400453 Specify 2nd library version outside the descriptor.
454
455 -s|-strict
456 Treat all compatibility warnings as problems. Add a number of \"Low\"
457 severity problems to the return value of the tool.
458
459 -headers-only
460 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
461 provide a low quality compatibility report with false positives and
462 without detecting of added/removed symbols.
463
464 Alternatively you can write \"none\" word to the <libs> section
465 in the XML-descriptor:
466 <libs>
467 none
468 </libs>
469
470 -objects-only
471 Check $SLIB_TYPE libraries without header files. It is easy to run, but may
472 provide a low quality compatibility report with false positives and
473 without analysis of changes in parameters and data types.
474
475 Alternatively you can write \"none\" word to the <headers> section
476 in the XML-descriptor:
477 <headers>
478 none
479 </headers>
480
481 -check-impl|-check-implementation
482 Compare canonified disassembled binary code of $SLIB_TYPE libraries to
483 detect changes in the implementation. Add \'Problems with Implementation\'
484 section to the report.
485
486 -show-retval
487 Show the symbol's return type in the report.
488
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400489 -symbols-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400490 This option allows to specify a file with a list of symbols (mangled
491 names in C++) that should be checked, other symbols will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400492
493 -skip-symbols PATH
494 The list of symbols that should NOT be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400495
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400496 -headers-list PATH
497 The file with a list of headers, that should be checked/dumped.
498
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400499 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400500 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400501
502 -header NAME
503 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400504
505 -use-dumps
506 Make dumps for two versions of a library and compare dumps. This should
507 increase the performance of the tool and decrease the system memory usage.
508
509 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400510 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400511
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400512 -dump-system NAME -sysroot DIR
513 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400514 create XML descriptors and make ABI dumps for each library. The result
515 set of ABI dumps can be compared (--cmp-systems) with the other one
516 created for other version of operating system in order to check them for
517 compatibility. Do not forget to specify -cross-gcc option if your target
518 system requires some specific version of GCC compiler (different from
519 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400520 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400521
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400522 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400523 The same as the previous option but takes an XML descriptor of the target
524 system as input, where you should describe it:
525
526 /* Primary sections */
527
528 <name>
529 /* Name of the system */
530 </name>
531
532 <headers>
533 /* The list of paths to header files and/or
534 directories with header files, one per line */
535 </headers>
536
537 <libs>
538 /* The list of paths to shared libraries and/or
539 directories with shared libraries, one per line */
540 </libs>
541
542 /* Optional sections */
543
544 <search_headers>
545 /* List of directories to be searched
546 for header files to automatically
547 generate include paths, one per line */
548 </search_headers>
549
550 <search_libs>
551 /* List of directories to be searched
552 for shared libraries to resolve
553 dependencies, one per line */
554 </search_libs>
555
556 <tools>
557 /* List of directories with tools used
558 for analysis (GCC toolchain), one per line */
559 </tools>
560
561 <cross_prefix>
562 /* GCC toolchain prefix.
563 Examples:
564 arm-linux-gnueabi
565 arm-none-symbianelf */
566 </cross_prefix>
567
568 <gcc_options>
569 /* Additional GCC options, one per line */
570 </gcc_options>
571
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400572 -sysinfo DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400573 This option may be used with -dump-system to dump ABI of operating
574 systems and configure the dumping process.
575 Default:
576 modules/Targets/{unix, symbian, windows}
577
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400578 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400579 Compare two system ABI dumps. Create compatibility reports for each
580 library and the common HTML report including the summary of test
581 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400582 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400583
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400584 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400585 The file with a list of libraries, that should be dumped by
586 the -dump-system option or should be checked by the -cmp-systems option.
587
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400588 -ext|-extended
589 If your library A is supposed to be used by other library B and you
590 want to control the ABI of B, then you should enable this option. The
591 tool will check for changes in all data types, even if they are not
592 used by any function in the library A. Such data types are not part
593 of the A library ABI, but may be a part of the ABI of the B library.
594
595 The short scheme is:
596 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
597
598 -q|-quiet
599 Print all messages to the file instead of stdout and stderr.
600 Default path (can be changed by -log-path option):
601 $COMMON_LOG_PATH
602
603 -stdout
604 Print analysis results (compatibility reports and ABI dumps) to stdout
605 instead of creating a file. This would allow piping data to other programs.
606
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400607 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400608 Change format of compatibility report.
609 Formats:
610 htm - HTML format (default)
611 xml - XML format
612
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400613 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400614 Change format of ABI dump.
615 Formats:
616 perl - Data::Dumper format (default)
617 xml - XML format
618
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400619 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400620 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400621
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400622 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400623 Set library language (C or C++). You can use this option if the tool
624 cannot auto-detect a language. This option may be useful for checking
625 C-library headers (--lang=C) in --headers-only or --extended modes.
626
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400627 -binary|-bin|-abi
628 Show \"Binary\" compatibility problems only.
629 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400630 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400631
632 -source|-src|-api
633 Show \"Source\" compatibility problems only.
634 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400635 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400636
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400637OTHER OPTIONS:
638 -test
639 Run internal tests. Create two binary incompatible versions of a sample
640 library and run the tool to check them for compatibility. This option
641 allows to check if the tool works correctly in the current environment.
642
643 -test-dump
644 Test ability to create, read and compare ABI dumps.
645
646 -debug
647 Debugging mode. Print debug info on the screen. Save intermediate
648 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400649 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400650
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400651 Also consider using --dump option for debugging the tool.
652
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400653 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400654 If your header files are written in C language and can be compiled
655 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
656 the tool about this and speedup the analysis.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400657
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400658 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400659 Path to file with the function parameter names. It can be used
660 for improving report view if the library header files have no
661 parameter names. File format:
662
663 func1;param1;param2;param3 ...
664 func2;param1;param2;param3 ...
665 ...
666
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400667 -relpath PATH
668 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400669 for dumping the library ABI (see -dump option).
670
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400671 -relpath1 PATH
672 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400673
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400674 -relpath2 PATH
675 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400676
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400677 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400678 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400679 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400680 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400681
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400682 -sort
683 Enable sorting of data in ABI dumps.
684
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400685 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400686 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400687 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400688 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400689
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400690 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400691 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400692 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400693 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400694
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400695 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400696 Path to \"Source\" compatibility report.
697 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400698 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400699
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400700 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400701 Log path for all messages.
702 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400703 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400704
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400705 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400706 Log path for 1st version of a library.
707 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400708 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400709
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400710 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400711 Log path for 2nd version of a library.
712 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400713 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400714
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400715 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400716 Change logging mode.
717 Modes:
718 w - overwrite old logs (default)
719 a - append old logs
720 n - do not write any logs
721
722 -list-affected
723 Generate file with the list of incompatible
724 symbols beside the HTML compatibility report.
725 Use 'c++filt \@file' command from GNU binutils
726 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400727 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400728 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400729 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400730
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400731 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400732 The component name in the title and summary of the HTML report.
733 Default:
734 library
735
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400736 -l-full|-lib-full NAME
737 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400738 will be displayed a name specified by -l option.
739
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400740 -b|-browse PROGRAM
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400741 Open report(s) in the browser (firefox, opera, etc.).
742
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400743 -open
744 Open report(s) in the default browser.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400745
746 -extra-info DIR
747 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400748
749 -extra-dump
750 Create extended ABI dump containing all symbols
751 from the translation unit.
752
753 -force
754 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400755
756 -tolerance LEVEL
757 Apply a set of heuristics to successfully compile input
758 header files. You can enable several tolerance levels by
759 joining them into one string (e.g. 13, 124, etc.).
760 Levels:
761 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
762 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
763 3 - skip headers that iclude non-Linux headers
764 4 - skip headers included by others
765
766 -tolerant
767 Enable highest tolerance level [1234].
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400768
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400769REPORT:
770 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400771 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400772
773 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400774 logs/LIB_NAME/V1/log.txt
775 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400776
777EXIT CODES:
778 0 - Compatible. The tool has run without any errors.
779 non-zero - Incompatible or the tool has run with errors.
780
781REPORT BUGS TO:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400782 Andrey Ponomarenko <aponomarenko\@rosalab.ru>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400783
784MORE INFORMATION:
785 ".$HomePage{"Wiki"}."
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400786 ".$HomePage{"Dev1"}."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400787}
788
789my $DescriptorTemplate = "
790<?xml version=\"1.0\" encoding=\"utf-8\"?>
791<descriptor>
792
793/* Primary sections */
794
795<version>
796 /* Version of the library */
797</version>
798
799<headers>
800 /* The list of paths to header files and/or
801 directories with header files, one per line */
802</headers>
803
804<libs>
805 /* The list of paths to shared libraries (*.$LIB_EXT) and/or
806 directories with shared libraries, one per line */
807</libs>
808
809/* Optional sections */
810
811<include_paths>
812 /* The list of include paths that will be provided
813 to GCC to compile library headers, one per line.
814 NOTE: If you define this section then the tool
815 will not automatically generate include paths */
816</include_paths>
817
818<add_include_paths>
819 /* The list of include paths that will be added
820 to the automatically generated include paths, one per line */
821</add_include_paths>
822
823<skip_include_paths>
824 /* The list of include paths that will be removed from the
825 list of automatically generated include paths, one per line */
826</skip_include_paths>
827
828<gcc_options>
829 /* Additional GCC options, one per line */
830</gcc_options>
831
832<include_preamble>
833 /* The list of header files that will be
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +0400834 included before other headers, one per line */
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400835</include_preamble>
836
837<defines>
838 /* The list of defines that will be added at the
839 headers compiling stage, one per line:
840 #define A B
841 #define C D */
842</defines>
843
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +0400844<add_namespaces>
845 /* The list of namespaces that should be added to the alanysis
846 if the tool cannot find them automatically, one per line */
847</add_namespaces>
848
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400849<skip_types>
850 /* The list of data types, that
851 should not be checked, one per line */
852</skip_types>
853
854<skip_symbols>
855 /* The list of functions (mangled/symbol names in C++),
856 that should not be checked, one per line */
857</skip_symbols>
858
859<skip_namespaces>
860 /* The list of C++ namespaces, that
861 should not be checked, one per line */
862</skip_namespaces>
863
864<skip_constants>
865 /* The list of constants that should
866 not be checked, one name per line */
867</skip_constants>
868
869<skip_headers>
870 /* The list of header files and/or directories
871 with header files that should not be checked, one per line */
872</skip_headers>
873
874<skip_libs>
875 /* The list of shared libraries and/or directories
876 with shared libraries that should not be checked, one per line */
877</skip_libs>
878
879<skip_including>
880 /* The list of header files, that cannot be included
881 directly (or non-self compiled ones), one per line */
882</skip_including>
883
884<search_headers>
885 /* List of directories to be searched
886 for header files to automatically
887 generate include paths, one per line. */
888</search_headers>
889
890<search_libs>
891 /* List of directories to be searched
892 for shared librariess to resolve
893 dependencies, one per line */
894</search_libs>
895
896<tools>
897 /* List of directories with tools used
898 for analysis (GCC toolchain), one per line */
899</tools>
900
901<cross_prefix>
902 /* GCC toolchain prefix.
903 Examples:
904 arm-linux-gnueabi
905 arm-none-symbianelf */
906</cross_prefix>
907
908</descriptor>";
909
910my %Operator_Indication = (
911 "not" => "~",
912 "assign" => "=",
913 "andassign" => "&=",
914 "orassign" => "|=",
915 "xorassign" => "^=",
916 "or" => "|",
917 "xor" => "^",
918 "addr" => "&",
919 "and" => "&",
920 "lnot" => "!",
921 "eq" => "==",
922 "ne" => "!=",
923 "lt" => "<",
924 "lshift" => "<<",
925 "lshiftassign" => "<<=",
926 "rshiftassign" => ">>=",
927 "call" => "()",
928 "mod" => "%",
929 "modassign" => "%=",
930 "subs" => "[]",
931 "land" => "&&",
932 "lor" => "||",
933 "rshift" => ">>",
934 "ref" => "->",
935 "le" => "<=",
936 "deref" => "*",
937 "mult" => "*",
938 "preinc" => "++",
939 "delete" => " delete",
940 "vecnew" => " new[]",
941 "vecdelete" => " delete[]",
942 "predec" => "--",
943 "postinc" => "++",
944 "postdec" => "--",
945 "plusassign" => "+=",
946 "plus" => "+",
947 "minus" => "-",
948 "minusassign" => "-=",
949 "gt" => ">",
950 "ge" => ">=",
951 "new" => " new",
952 "multassign" => "*=",
953 "divassign" => "/=",
954 "div" => "/",
955 "neg" => "-",
956 "pos" => "+",
957 "memref" => "->*",
958 "compound" => "," );
959
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400960my %UnknownOperator;
961
962my %NodeType= (
963 "array_type" => "Array",
964 "binfo" => "Other",
965 "boolean_type" => "Intrinsic",
966 "complex_type" => "Intrinsic",
967 "const_decl" => "Other",
968 "enumeral_type" => "Enum",
969 "field_decl" => "Other",
970 "function_decl" => "Other",
971 "function_type" => "FunctionType",
972 "identifier_node" => "Other",
973 "integer_cst" => "Other",
974 "integer_type" => "Intrinsic",
975 "method_type" => "MethodType",
976 "namespace_decl" => "Other",
977 "parm_decl" => "Other",
978 "pointer_type" => "Pointer",
979 "real_cst" => "Other",
980 "real_type" => "Intrinsic",
981 "record_type" => "Struct",
982 "reference_type" => "Ref",
983 "string_cst" => "Other",
984 "template_decl" => "Other",
985 "template_type_parm" => "Other",
986 "tree_list" => "Other",
987 "tree_vec" => "Other",
988 "type_decl" => "Other",
989 "union_type" => "Union",
990 "var_decl" => "Other",
991 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400992 "nop_expr" => "Other", #
993 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400994 "offset_type" => "Other" );
995
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400996my %CppKeywords_C = map {$_=>1} (
997 # C++ 2003 keywords
998 "public",
999 "protected",
1000 "private",
1001 "default",
1002 "template",
1003 "new",
1004 #"asm",
1005 "dynamic_cast",
1006 "auto",
1007 "try",
1008 "namespace",
1009 "typename",
1010 "using",
1011 "reinterpret_cast",
1012 "friend",
1013 "class",
1014 "virtual",
1015 "const_cast",
1016 "mutable",
1017 "static_cast",
1018 "export",
1019 # C++0x keywords
1020 "noexcept",
1021 "nullptr",
1022 "constexpr",
1023 "static_assert",
1024 "explicit",
1025 # cannot be used as a macro name
1026 # as it is an operator in C++
1027 "and",
1028 #"and_eq",
1029 "not",
1030 #"not_eq",
1031 "or"
1032 #"or_eq",
1033 #"bitand",
1034 #"bitor",
1035 #"xor",
1036 #"xor_eq",
1037 #"compl"
1038);
1039
1040my %CppKeywords_F = map {$_=>1} (
1041 "delete",
1042 "catch",
1043 "alignof",
1044 "thread_local",
1045 "decltype",
1046 "typeid"
1047);
1048
1049my %CppKeywords_O = map {$_=>1} (
1050 "bool",
1051 "register",
1052 "inline",
1053 "operator"
1054);
1055
1056my %CppKeywords_A = map {$_=>1} (
1057 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001058 "throw",
1059 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001060);
1061
1062foreach (keys(%CppKeywords_C),
1063keys(%CppKeywords_F),
1064keys(%CppKeywords_O)) {
1065 $CppKeywords_A{$_}=1;
1066}
1067
1068# Header file extensions as described by gcc
1069my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
1070
1071my %IntrinsicMangling = (
1072 "void" => "v",
1073 "bool" => "b",
1074 "wchar_t" => "w",
1075 "char" => "c",
1076 "signed char" => "a",
1077 "unsigned char" => "h",
1078 "short" => "s",
1079 "unsigned short" => "t",
1080 "int" => "i",
1081 "unsigned int" => "j",
1082 "long" => "l",
1083 "unsigned long" => "m",
1084 "long long" => "x",
1085 "__int64" => "x",
1086 "unsigned long long" => "y",
1087 "__int128" => "n",
1088 "unsigned __int128" => "o",
1089 "float" => "f",
1090 "double" => "d",
1091 "long double" => "e",
1092 "__float80" => "e",
1093 "__float128" => "g",
1094 "..." => "z"
1095);
1096
1097my %StdcxxMangling = (
1098 "3std"=>"St",
1099 "3std9allocator"=>"Sa",
1100 "3std12basic_string"=>"Sb",
1101 "3std12basic_stringIcE"=>"Ss",
1102 "3std13basic_istreamIcE"=>"Si",
1103 "3std13basic_ostreamIcE"=>"So",
1104 "3std14basic_iostreamIcE"=>"Sd"
1105);
1106
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04001107my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001108
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001109my %ConstantSuffix = (
1110 "unsigned int"=>"u",
1111 "long"=>"l",
1112 "unsigned long"=>"ul",
1113 "long long"=>"ll",
1114 "unsigned long long"=>"ull"
1115);
1116
1117my %ConstantSuffixR =
1118reverse(%ConstantSuffix);
1119
1120my %OperatorMangling = (
1121 "~" => "co",
1122 "=" => "aS",
1123 "|" => "or",
1124 "^" => "eo",
1125 "&" => "an",#ad (addr)
1126 "==" => "eq",
1127 "!" => "nt",
1128 "!=" => "ne",
1129 "<" => "lt",
1130 "<=" => "le",
1131 "<<" => "ls",
1132 "<<=" => "lS",
1133 ">" => "gt",
1134 ">=" => "ge",
1135 ">>" => "rs",
1136 ">>=" => "rS",
1137 "()" => "cl",
1138 "%" => "rm",
1139 "[]" => "ix",
1140 "&&" => "aa",
1141 "||" => "oo",
1142 "*" => "ml",#de (deref)
1143 "++" => "pp",#
1144 "--" => "mm",#
1145 "new" => "nw",
1146 "delete" => "dl",
1147 "new[]" => "na",
1148 "delete[]" => "da",
1149 "+=" => "pL",
1150 "+" => "pl",#ps (pos)
1151 "-" => "mi",#ng (neg)
1152 "-=" => "mI",
1153 "*=" => "mL",
1154 "/=" => "dV",
1155 "&=" => "aN",
1156 "|=" => "oR",
1157 "%=" => "rM",
1158 "^=" => "eO",
1159 "/" => "dv",
1160 "->*" => "pm",
1161 "->" => "pt",#rf (ref)
1162 "," => "cm",
1163 "?" => "qu",
1164 "." => "dt",
1165 "sizeof"=> "sz"#st
1166);
1167
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001168my %Intrinsic_Keywords = map {$_=>1} (
1169 "true",
1170 "false",
1171 "_Bool",
1172 "_Complex",
1173 "const",
1174 "int",
1175 "long",
1176 "void",
1177 "short",
1178 "float",
1179 "volatile",
1180 "restrict",
1181 "unsigned",
1182 "signed",
1183 "char",
1184 "double",
1185 "class",
1186 "struct",
1187 "union",
1188 "enum"
1189);
1190
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001191my %GlibcHeader = map {$_=>1} (
1192 "aliases.h",
1193 "argp.h",
1194 "argz.h",
1195 "assert.h",
1196 "cpio.h",
1197 "ctype.h",
1198 "dirent.h",
1199 "envz.h",
1200 "errno.h",
1201 "error.h",
1202 "execinfo.h",
1203 "fcntl.h",
1204 "fstab.h",
1205 "ftw.h",
1206 "glob.h",
1207 "grp.h",
1208 "iconv.h",
1209 "ifaddrs.h",
1210 "inttypes.h",
1211 "langinfo.h",
1212 "limits.h",
1213 "link.h",
1214 "locale.h",
1215 "malloc.h",
1216 "math.h",
1217 "mntent.h",
1218 "monetary.h",
1219 "nl_types.h",
1220 "obstack.h",
1221 "printf.h",
1222 "pwd.h",
1223 "regex.h",
1224 "sched.h",
1225 "search.h",
1226 "setjmp.h",
1227 "shadow.h",
1228 "signal.h",
1229 "spawn.h",
1230 "stdarg.h",
1231 "stdint.h",
1232 "stdio.h",
1233 "stdlib.h",
1234 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001235 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001236 "tar.h",
1237 "termios.h",
1238 "time.h",
1239 "ulimit.h",
1240 "unistd.h",
1241 "utime.h",
1242 "wchar.h",
1243 "wctype.h",
1244 "wordexp.h" );
1245
1246my %GlibcDir = map {$_=>1} (
1247 "arpa",
1248 "bits",
1249 "gnu",
1250 "netinet",
1251 "net",
1252 "nfs",
1253 "rpc",
1254 "sys",
1255 "linux" );
1256
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001257my %WinHeaders = map {$_=>1} (
1258 "dos.h",
1259 "process.h",
1260 "winsock.h",
1261 "config-win.h",
1262 "mem.h",
1263 "windows.h",
1264 "winsock2.h",
1265 "crtdbg.h",
1266 "ws2tcpip.h"
1267);
1268
1269my %ObsoleteHeaders = map {$_=>1} (
1270 "iostream.h",
1271 "fstream.h"
1272);
1273
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001274my %AlienHeaders = map {$_=>1} (
1275 # Solaris
1276 "thread.h",
1277 "sys/atomic.h",
1278 # HPUX
1279 "sys/stream.h",
1280 # Symbian
1281 "AknDoc.h",
1282 # Atari ST
1283 "ext.h",
1284 "tos.h",
1285 # MS-DOS
1286 "alloc.h",
1287 # Sparc
1288 "sys/atomic.h"
1289);
1290
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001291my %ConfHeaders = map {$_=>1} (
1292 "atomic",
1293 "conf.h",
1294 "config.h",
1295 "configure.h",
1296 "build.h",
1297 "setup.h"
1298);
1299
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001300my %LocalIncludes = map {$_=>1} (
1301 "/usr/local/include",
1302 "/usr/local" );
1303
1304my %OS_AddPath=(
1305# These paths are needed if the tool cannot detect them automatically
1306 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001307 "include"=>[
1308 "/Library",
1309 "/Developer/usr/include"
1310 ],
1311 "lib"=>[
1312 "/Library",
1313 "/Developer/usr/lib"
1314 ],
1315 "bin"=>[
1316 "/Developer/usr/bin"
1317 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001318 },
1319 "beos"=>{
1320 # Haiku has GCC 2.95.3 by default
1321 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001322 "include"=>[
1323 "/boot/common",
1324 "/boot/develop"
1325 ],
1326 "lib"=>[
1327 "/boot/common/lib",
1328 "/boot/system/lib",
1329 "/boot/apps"
1330 ],
1331 "bin"=>[
1332 "/boot/common/bin",
1333 "/boot/system/bin",
1334 "/boot/develop/abi"
1335 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001337);
1338
1339my %Slash_Type=(
1340 "default"=>"/",
1341 "windows"=>"\\"
1342);
1343
1344my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1345
1346# Global Variables
1347my %COMMON_LANGUAGE=(
1348 1 => "C",
1349 2 => "C" );
1350
1351my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001352my $MAX_CPPFILT_FILE_SIZE = 50000;
1353my $CPPFILT_SUPPORT_FILE;
1354
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001355my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1356
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001357my $STDCXX_TESTING = 0;
1358my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001359my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001360
1361my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
1362my $CheckObjectsOnly = $CheckObjectsOnly_Opt;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001363
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001364my $TargetComponent;
1365
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001366my $CheckUndefined = 0;
1367
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001368# Set Target Component Name
1369if($TargetComponent_Opt) {
1370 $TargetComponent = lc($TargetComponent_Opt);
1371}
1372else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001373{ # default: library
1374 # other components: header, system, ...
1375 $TargetComponent = "library";
1376}
1377
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001378my $TOP_REF = "<a style='font-size:11px;' href='#Top'>to the top</a>";
1379
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001380my $SystemRoot;
1381
1382my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001383my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001384my %LOG_PATH;
1385my %DEBUG_PATH;
1386my %Cache;
1387my %LibInfo;
1388my $COMPILE_ERRORS = 0;
1389my %CompilerOptions;
1390my %CheckedDyLib;
1391my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1392
1393# Constants (#defines)
1394my %Constants;
1395my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001396my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001397
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001398# Extra Info
1399my %SymbolHeader;
1400my %KnownLibs;
1401
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001402# Types
1403my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001404my %TemplateInstance;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04001405my %TemplateDecl;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001406my %SkipTypes = (
1407 "1"=>{},
1408 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001409my %CheckedTypes;
1410my %TName_Tid;
1411my %EnumMembName_Id;
1412my %NestedNameSpaces = (
1413 "1"=>{},
1414 "2"=>{} );
1415my %UsedType;
1416my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001417my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001418my %ClassVTable;
1419my %ClassVTable_Content;
1420my %VTableClass;
1421my %AllocableClass;
1422my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001423my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001424my %Class_SubClasses;
1425my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001426my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001427my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001428
1429# Typedefs
1430my %Typedef_BaseName;
1431my %Typedef_Tr;
1432my %Typedef_Eq;
1433my %StdCxxTypedef;
1434my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001435my %MissedBase;
1436my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001437my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001438
1439# Symbols
1440my %SymbolInfo;
1441my %tr_name;
1442my %mangled_name_gcc;
1443my %mangled_name;
1444my %SkipSymbols = (
1445 "1"=>{},
1446 "2"=>{} );
1447my %SkipNameSpaces = (
1448 "1"=>{},
1449 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001450my %AddNameSpaces = (
1451 "1"=>{},
1452 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001453my %SymbolsList;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001454my %SkipSymbolsList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001455my %SymbolsList_App;
1456my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001457my %Symbol_Library = (
1458 "1"=>{},
1459 "2"=>{} );
1460my %Library_Symbol = (
1461 "1"=>{},
1462 "2"=>{} );
1463my %DepSymbol_Library = (
1464 "1"=>{},
1465 "2"=>{} );
1466my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001467 "1"=>{},
1468 "2"=>{} );
1469my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001470my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001471my %AddIntParams;
1472my %Interface_Impl;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001473my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001474my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001475my %Library_Needed= (
1476 "1"=>{},
1477 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001478
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001479# Extra Info
1480my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001481my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001482
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001483# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001484my %Include_Preamble = (
1485 "1"=>[],
1486 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001487my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001488my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001489my %HeaderName_Paths;
1490my %Header_Dependency;
1491my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001492my %Include_Paths = (
1493 "1"=>[],
1494 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001495my %INC_PATH_AUTODETECT = (
1496 "1"=>1,
1497 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001498my %Add_Include_Paths = (
1499 "1"=>[],
1500 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001501my %Skip_Include_Paths;
1502my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001503my %Header_ErrorRedirect;
1504my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001505my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001506my %Header_ShouldNotBeUsed;
1507my %RecursiveIncludes;
1508my %Header_Include_Prefix;
1509my %SkipHeaders;
1510my %SkipHeadersList=(
1511 "1"=>{},
1512 "2"=>{} );
1513my %SkipLibs;
1514my %Include_Order;
1515my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001516my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001517my %TUnit_Funcs;
1518my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001519
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001520my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001521 "1"=>0,
1522 "2"=>0 );
1523my %AutoPreambleMode = (
1524 "1"=>0,
1525 "2"=>0 );
1526my %MinGWMode = (
1527 "1"=>0,
1528 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001529my %Cpp0xMode = (
1530 "1"=>0,
1531 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001532
1533# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001534my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001535my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001536my %RegisteredSONAMEs;
1537my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001538
1539# System Objects
1540my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001541my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001542my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001543
1544# System Headers
1545my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001546my @DefaultCppPaths;
1547my @DefaultGccPaths;
1548my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001549my %DefaultCppHeader;
1550my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001551my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001552
1553# Merging
1554my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001555my $Version;
1556my %AddedInt;
1557my %RemovedInt;
1558my %AddedInt_Virt;
1559my %RemovedInt_Virt;
1560my %VirtualReplacement;
1561my %ChangedTypedef;
1562my %CompatRules;
1563my %IncompleteRules;
1564my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001565my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001566my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001567my %ReturnedClass;
1568my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001569my %SourceAlternative;
1570my %SourceAlternative_B;
1571my %SourceReplacement;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001572
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001573# Calling Conventions
1574my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001575 1=>{ "R"=>0, "P"=>0 },
1576 2=>{ "R"=>0, "P"=>0 }
1577);
1578
1579# ABI Dump
1580my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001581
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001582# OS Compliance
1583my %TargetLibs;
1584my %TargetHeaders;
1585
1586# OS Specifics
1587my $OStarget = $OSgroup;
1588my %TargetTools;
1589
1590# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001591my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001592
1593# Recursion locks
1594my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001595my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001596my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001597my @RecurInclude;
1598my @RecurConstant;
1599
1600# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001601my %SystemPaths = (
1602 "include"=>[],
1603 "lib"=>[],
1604 "bin"=>[]
1605);
1606my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001607my $GCC_PATH;
1608
1609# Symbols versioning
1610my %SymVer = (
1611 "1"=>{},
1612 "2"=>{} );
1613
1614# Problem descriptions
1615my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001616my %CompatProblems_Constants;
1617my %CompatProblems_Impl;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001618my %TotalAffected;
1619
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001620# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001621my $ContentID = 1;
1622my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1623my $ContentSpanStart_Affected = "<span class=\"section_affected\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1624my $ContentSpanStart_Info = "<span class=\"section_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1625my $ContentSpanEnd = "</span>\n";
1626my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1627my $ContentDivEnd = "</div>\n";
1628my $Content_Counter = 0;
1629
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001630# Modes
1631my $JoinReport = 1;
1632my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001633
1634sub get_Modules()
1635{
1636 my $TOOL_DIR = get_dirname($0);
1637 if(not $TOOL_DIR)
1638 { # patch for MS Windows
1639 $TOOL_DIR = ".";
1640 }
1641 my @SEARCH_DIRS = (
1642 # tool's directory
1643 abs_path($TOOL_DIR),
1644 # relative path to modules
1645 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001646 # install path
1647 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001648 );
1649 foreach my $DIR (@SEARCH_DIRS)
1650 {
1651 if(not is_abs($DIR))
1652 { # relative path
1653 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1654 }
1655 if(-d $DIR."/modules") {
1656 return $DIR."/modules";
1657 }
1658 }
1659 exitStatus("Module_Error", "can't find modules");
1660}
1661
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001662my %LoadedModules = ();
1663
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001664sub loadModule($)
1665{
1666 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001667 if(defined $LoadedModules{$Name}) {
1668 return;
1669 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001670 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1671 if(not -f $Path) {
1672 exitStatus("Module_Error", "can't access \'$Path\'");
1673 }
1674 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001675 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001676}
1677
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001678sub readModule($$)
1679{
1680 my ($Module, $Name) = @_;
1681 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1682 if(not -f $Path) {
1683 exitStatus("Module_Error", "can't access \'$Path\'");
1684 }
1685 return readFile($Path);
1686}
1687
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001688sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001689{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001690 my $Number = $_[0];
1691 if(not $Number) {
1692 $Number = 1;
1693 }
1694 else {
1695 $Number = int($Number)+1;
1696 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001697 if($Number>3) {
1698 return $Number."th";
1699 }
1700 elsif($Number==1) {
1701 return "1st";
1702 }
1703 elsif($Number==2) {
1704 return "2nd";
1705 }
1706 elsif($Number==3) {
1707 return "3rd";
1708 }
1709 else {
1710 return $Number;
1711 }
1712}
1713
1714sub search_Tools($)
1715{
1716 my $Name = $_[0];
1717 return "" if(not $Name);
1718 if(my @Paths = keys(%TargetTools))
1719 {
1720 foreach my $Path (@Paths)
1721 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001722 if(-f join_P($Path, $Name)) {
1723 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001724 }
1725 if($CrossPrefix)
1726 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001727 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001728 if(-f $Candidate) {
1729 return $Candidate;
1730 }
1731 }
1732 }
1733 }
1734 else {
1735 return "";
1736 }
1737}
1738
1739sub synch_Cmd($)
1740{
1741 my $Name = $_[0];
1742 if(not $GCC_PATH)
1743 { # GCC was not found yet
1744 return "";
1745 }
1746 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001747 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001748 return $Candidate;
1749 }
1750 return "";
1751}
1752
1753sub get_CmdPath($)
1754{
1755 my $Name = $_[0];
1756 return "" if(not $Name);
1757 if(defined $Cache{"get_CmdPath"}{$Name}) {
1758 return $Cache{"get_CmdPath"}{$Name};
1759 }
1760 my %BinUtils = map {$_=>1} (
1761 "c++filt",
1762 "objdump",
1763 "readelf"
1764 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001765 if($BinUtils{$Name} and $GCC_PATH)
1766 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001767 if(my $Dir = get_dirname($GCC_PATH)) {
1768 $TargetTools{$Dir}=1;
1769 }
1770 }
1771 my $Path = search_Tools($Name);
1772 if(not $Path and $OSgroup eq "windows") {
1773 $Path = search_Tools($Name.".exe");
1774 }
1775 if(not $Path and $BinUtils{$Name})
1776 {
1777 if($CrossPrefix)
1778 { # user-defined prefix
1779 $Path = search_Cmd($CrossPrefix."-".$Name);
1780 }
1781 }
1782 if(not $Path and $BinUtils{$Name})
1783 {
1784 if(my $Candidate = synch_Cmd($Name))
1785 { # synch with GCC
1786 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001787 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001788 if(-f $Candidate) {
1789 $Path = $Candidate;
1790 }
1791 }
1792 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001793 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001794 $Path = $Candidate;
1795 }
1796 }
1797 }
1798 if(not $Path) {
1799 $Path = search_Cmd($Name);
1800 }
1801 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001802 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001803 $Path=search_Cmd($Name.".exe");
1804 }
1805 if($Path=~/\s/) {
1806 $Path = "\"".$Path."\"";
1807 }
1808 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1809}
1810
1811sub search_Cmd($)
1812{
1813 my $Name = $_[0];
1814 return "" if(not $Name);
1815 if(defined $Cache{"search_Cmd"}{$Name}) {
1816 return $Cache{"search_Cmd"}{$Name};
1817 }
1818 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1819 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1820 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001821 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001822 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001823 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001824 if(-f $CmdPath)
1825 {
1826 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001827 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001828 }
1829 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1830 }
1831 }
1832 return ($Cache{"search_Cmd"}{$Name} = "");
1833}
1834
1835sub get_CmdPath_Default($)
1836{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001837 return "" if(not $_[0]);
1838 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1839 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001840 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001841 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1842}
1843
1844sub get_CmdPath_Default_I($)
1845{ # search in PATH
1846 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001847 if($Name=~/find/)
1848 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001849 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001850 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001851 }
1852 }
1853 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001854 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001855 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001856 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001857 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001858 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001859 if($OSgroup eq "windows")
1860 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001861 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001862 return $Name;
1863 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001864 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001865 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001866 {
1867 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001868 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001869 }
1870 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001871 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001872}
1873
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001874sub classifyPath($)
1875{
1876 my $Path = $_[0];
1877 if($Path=~/[\*\[]/)
1878 { # wildcard
1879 $Path=~s/\*/.*/g;
1880 $Path=~s/\\/\\\\/g;
1881 return ($Path, "Pattern");
1882 }
1883 elsif($Path=~/[\/\\]/)
1884 { # directory or relative path
1885 return (path_format($Path, $OSgroup), "Path");
1886 }
1887 else {
1888 return ($Path, "Name");
1889 }
1890}
1891
1892sub readDescriptor($$)
1893{
1894 my ($LibVersion, $Content) = @_;
1895 return if(not $LibVersion);
1896 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1897 if(not $Content) {
1898 exitStatus("Error", "$DName is empty");
1899 }
1900 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001901 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001902 }
1903 $Content=~s/\/\*(.|\n)+?\*\///g;
1904 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001905
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001906 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1907 if($TargetVersion{$LibVersion}) {
1908 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1909 }
1910 if(not $Descriptor{$LibVersion}{"Version"}) {
1911 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1912 }
1913 if($Content=~/{RELPATH}/)
1914 {
1915 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1916 $Content =~ s/{RELPATH}/$RelDir/g;
1917 }
1918 else
1919 {
1920 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1921 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1922 }
1923 }
1924
1925 if(not $CheckObjectsOnly_Opt)
1926 {
1927 my $DHeaders = parseTag(\$Content, "headers");
1928 if(not $DHeaders) {
1929 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1930 }
1931 elsif(lc($DHeaders) ne "none")
1932 { # append the descriptor headers list
1933 if($Descriptor{$LibVersion}{"Headers"})
1934 { # multiple descriptors
1935 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
1936 }
1937 else {
1938 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1939 }
1940 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1941 {
1942 if(not -e $Path) {
1943 exitStatus("Access_Error", "can't access \'$Path\'");
1944 }
1945 }
1946 }
1947 }
1948 if(not $CheckHeadersOnly_Opt)
1949 {
1950 my $DObjects = parseTag(\$Content, "libs");
1951 if(not $DObjects) {
1952 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1953 }
1954 elsif(lc($DObjects) ne "none")
1955 { # append the descriptor libraries list
1956 if($Descriptor{$LibVersion}{"Libs"})
1957 { # multiple descriptors
1958 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1959 }
1960 else {
1961 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1962 }
1963 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1964 {
1965 if(not -e $Path) {
1966 exitStatus("Access_Error", "can't access \'$Path\'");
1967 }
1968 }
1969 }
1970 }
1971 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1972 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001973 if(not -d $Path) {
1974 exitStatus("Access_Error", "can't access directory \'$Path\'");
1975 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001976 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001977 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001978 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001979 }
1980 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
1981 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001982 if(not -d $Path) {
1983 exitStatus("Access_Error", "can't access directory \'$Path\'");
1984 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001985 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001986 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001987 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001988 }
1989 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
1990 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001991 if(not -d $Path) {
1992 exitStatus("Access_Error", "can't access directory \'$Path\'");
1993 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001994 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001995 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001996 push_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001997 $TargetTools{$Path}=1;
1998 }
1999 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
2000 $CrossPrefix = $Prefix;
2001 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002002 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002003 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
2004 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002005 if(not -d $Path) {
2006 exitStatus("Access_Error", "can't access directory \'$Path\'");
2007 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002008 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002009 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002010 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002011 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002012 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002013 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
2014 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002015 if(not -d $Path) {
2016 exitStatus("Access_Error", "can't access directory \'$Path\'");
2017 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002018 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002019 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002020 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002021 }
2022 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002023 { # skip some auto-generated include paths
2024 if(not is_abs($Path))
2025 {
2026 if(my $P = abs_path($Path)) {
2027 $Path = $P;
2028 }
2029 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002030 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002031 }
2032 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002033 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002034 my ($CPath, $Type) = classifyPath($Path);
2035 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002036 }
2037 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002038 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
2039 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002040 if($Option!~/\A\-(Wl|l|L)/)
2041 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002042 $CompilerOptions{$LibVersion} .= " ".$Option;
2043 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002044 }
2045 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
2046 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
2047 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002048 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002049 my ($CPath, $Type) = classifyPath($Path);
2050 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002051 }
2052 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
2053 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
2054 {
2055 my ($CPath, $Type) = classifyPath($Path);
2056 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
2057 }
2058 if(my $DDefines = parseTag(\$Content, "defines"))
2059 {
2060 if($Descriptor{$LibVersion}{"Defines"})
2061 { # multiple descriptors
2062 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
2063 }
2064 else {
2065 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
2066 }
2067 }
2068 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
2069 {
2070 if($Order=~/\A(.+):(.+)\Z/) {
2071 $Include_Order{$LibVersion}{$1} = $2;
2072 }
2073 }
2074 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
2075 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002076 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002077 $SkipTypes{$LibVersion}{$Type_Name} = 1;
2078 }
2079 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
2080 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002081 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002082 $SkipSymbols{$LibVersion}{$Symbol} = 1;
2083 }
2084 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
2085 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
2086 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04002087 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
2088 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
2089 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002090 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
2091 $SkipConstants{$LibVersion}{$Constant} = 1;
2092 }
2093 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
2094 {
2095 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002096 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002097 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
2098 }
2099 else {
2100 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2101 }
2102 }
2103}
2104
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002105sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002106{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002107 my $CodeRef = shift(@_);
2108 my $Tag = shift(@_);
2109 if(not $Tag or not $CodeRef) {
2110 return undef;
2111 }
2112 my $Sp = 0;
2113 if(@_) {
2114 $Sp = shift(@_);
2115 }
2116 my $Start = index(${$CodeRef}, "<$Tag>");
2117 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002118 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002119 my $End = index(${$CodeRef}, "</$Tag>");
2120 if($End!=-1)
2121 {
2122 my $TS = length($Tag)+3;
2123 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2124 substr($Content, 0, $TS-1, ""); # cut start tag
2125 substr($Content, -$TS, $TS, ""); # cut end tag
2126 if(not $Sp)
2127 {
2128 $Content=~s/\A\s+//g;
2129 $Content=~s/\s+\Z//g;
2130 }
2131 if(substr($Content, 0, 1) ne "<") {
2132 $Content = xmlSpecChars_R($Content);
2133 }
2134 return $Content;
2135 }
2136 }
2137 return undef;
2138}
2139
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002140sub getInfo($)
2141{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002142 my $DumpPath = $_[0];
2143 return if(not $DumpPath or not -f $DumpPath);
2144
2145 readTUDump($DumpPath);
2146
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002147 # processing info
2148 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002149
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002150 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002151 setAnonTypedef_All();
2152 }
2153
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002154 getTypeInfo_All();
2155 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002156 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002157 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002158 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002159
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002160
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002161 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002162 %LibInfo = ();
2163 %TemplateInstance = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002164 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002165 %TemplateDecl = ();
2166 %StdCxxTypedef = ();
2167 %MissedTypedef = ();
2168 %Typedef_Tr = ();
2169 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002170 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002171
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002172 # clean cache
2173 delete($Cache{"getTypeAttr"});
2174 delete($Cache{"getTypeDeclId"});
2175
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002176 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002177 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002178 foreach (keys(%{$TypeInfo{$Version}}))
2179 {
2180 if($TypeInfo{$Version}{$_}{"Artificial"}) {
2181 delete($TypeInfo{$Version}{$_});
2182 }
2183 }
2184 }
2185 else
2186 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002187 if($BinaryOnly and not $ExtendedCheck)
2188 { # --binary
2189 removeUnused($Version, "All");
2190 }
2191 else {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002192 removeUnused($Version, "Extended");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002193 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002194 }
2195
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002196 if($Debug) {
2197 # debugMangling($Version);
2198 }
2199}
2200
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002201sub readTUDump($)
2202{
2203 my $DumpPath = $_[0];
2204
2205 open(TU_DUMP, $DumpPath);
2206 local $/ = undef;
2207 my $Content = <TU_DUMP>;
2208 close(TU_DUMP);
2209
2210 unlink($DumpPath);
2211
2212 $Content=~s/\n[ ]+/ /g;
2213 my @Lines = split("\n", $Content);
2214
2215 # clean memory
2216 undef $Content;
2217
2218 $MAX_ID = $#Lines+1;
2219
2220 foreach (0 .. $#Lines)
2221 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002222 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002223 { # get a number and attributes of a node
2224 next if(not $NodeType{$2});
2225 $LibInfo{$Version}{"info_type"}{$1}=$2;
2226 $LibInfo{$Version}{"info"}{$1}=$3;
2227 }
2228
2229 # clean memory
2230 delete($Lines[$_]);
2231 }
2232
2233 # clean memory
2234 undef @Lines;
2235}
2236
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002237sub simplifyConstants()
2238{
2239 foreach my $Constant (keys(%{$Constants{$Version}}))
2240 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002241 if(defined $Constants{$Version}{$Constant}{"Header"})
2242 {
2243 my $Value = $Constants{$Version}{$Constant}{"Value"};
2244 if(defined $EnumConstants{$Version}{$Value}) {
2245 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2246 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002247 }
2248 }
2249}
2250
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002251sub simplifyNames()
2252{
2253 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2254 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002255 if($Typedef_Eq{$Version}{$Base}) {
2256 next;
2257 }
2258 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2259 if($#Translations==0)
2260 {
2261 if(length($Translations[0])<=length($Base)) {
2262 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2263 }
2264 }
2265 else
2266 { # select most appropriate
2267 foreach my $Tr (@Translations)
2268 {
2269 if($Base=~/\A\Q$Tr\E/)
2270 {
2271 $Typedef_Eq{$Version}{$Base} = $Tr;
2272 last;
2273 }
2274 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002275 }
2276 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002277 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002278 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002279 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002280 if(not $TypeName) {
2281 next;
2282 }
2283 next if(index($TypeName,"<")==-1);# template instances only
2284 if($TypeName=~/>(::\w+)+\Z/)
2285 { # skip unused types
2286 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002287 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002288 foreach my $Base (sort {length($b)<=>length($a)}
2289 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002290 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002291 next if(not $Base);
2292 next if(index($TypeName,$Base)==-1);
2293 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002294 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002295 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002296 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2297 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2298 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002299 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002300 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2301 {
2302 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2303 {
2304 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2305 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002306 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002307 }
2308 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002309 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002310 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002311 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002312 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002313 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2314 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002315 }
2316}
2317
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002318sub setAnonTypedef_All()
2319{
2320 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2321 {
2322 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2323 {
2324 if(isAnon(getNameByInfo($InfoId))) {
2325 $TypedefToAnon{getTypeId($InfoId)} = 1;
2326 }
2327 }
2328 }
2329}
2330
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002331sub setTemplateParams_All()
2332{
2333 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2334 {
2335 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2336 setTemplateParams($_);
2337 }
2338 }
2339}
2340
2341sub setTemplateParams($)
2342{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002343 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002344 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002345 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002346 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002347 my $TmplInst_Id = $2;
2348 setTemplateInstParams($TmplInst_Id);
2349 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
2350 setTemplateInstParams($TmplInst_Id);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002351 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002352 }
2353 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002354 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002355 {
2356 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2357 {
2358 if($IType eq "record_type") {
2359 $TemplateDecl{$Version}{$TypeId}=1;
2360 }
2361 }
2362 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002363}
2364
2365sub setTemplateInstParams($)
2366{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002367 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002368 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002369 my ($Params_InfoId, $ElemId) = ();
2370 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2371 $Params_InfoId = $1;
2372 }
2373 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2374 $ElemId = $1;
2375 }
2376 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002377 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002378 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2379 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2380 {
2381 my ($PPos, $PTypeId) = ($1, $2);
2382 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2383 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002384 if($PType eq "template_type_parm")
2385 {
2386 $TemplateDecl{$Version}{$ElemId}=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002387 return;
2388 }
2389 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002390 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2391 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002392 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002393 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002394 else
2395 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002396 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002397 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002398 }
2399 }
2400 }
2401}
2402
2403sub getTypeDeclId($)
2404{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002405 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002406 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002407 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2408 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2409 }
2410 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2411 {
2412 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2413 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2414 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002415 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002416 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002417 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002418}
2419
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002420sub getTypeInfo_All()
2421{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002422 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002423 { # support for GCC < 4.5
2424 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2425 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2426 # FIXME: check GCC versions
2427 addMissedTypes_Pre();
2428 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002429
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002430 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002431 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002432 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2433 if($IType=~/_type\Z/ and $IType ne "function_type"
2434 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002435 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002436 }
2437 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002438
2439 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002440 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002441 "Name" => "...",
2442 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002443 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002444 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002445 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002446
2447 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002448 { # support for GCC < 4.5
2449 addMissedTypes_Post();
2450 }
2451}
2452
2453sub addMissedTypes_Pre()
2454{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002455 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002456 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2457 { # detecting missed typedefs
2458 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2459 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002460 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002461 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002462 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002463 if($TypeType eq "Unknown")
2464 { # template_type_parm
2465 next;
2466 }
2467 my $TypeDeclId = getTypeDeclId($TypeId);
2468 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2469 my $TypedefName = getNameByInfo($MissedTDid);
2470 next if(not $TypedefName);
2471 next if($TypedefName eq "__float80");
2472 next if(isAnon($TypedefName));
2473 if(not $TypeDeclId
2474 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002475 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002476 }
2477 }
2478 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002479 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002480 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002481 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002482 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002483 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002484 next;
2485 }
2486 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002487 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002488 if(not $TypedefName) {
2489 next;
2490 }
2491 $MAX_ID++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002492 my %MissedInfo = ( # typedef info
2493 "Name" => $TypedefName,
2494 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002495 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002496 "Type" => "Typedef",
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002497 "Tid" => "$MAX_ID" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002498 my ($H, $L) = getLocation($MissedTDid);
2499 $MissedInfo{"Header"} = $H;
2500 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002501 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002502 { # other types
2503 next;
2504 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002505 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002506 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002507 next;
2508 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002509 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002510 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002511 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002512 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002513 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002514 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002515 next;
2516 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002517 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002518 next;
2519 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002520 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002521 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002522 next;
2523 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002524 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002525 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002526 next;
2527 }
2528 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002529
2530 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2531
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002532 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002533 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002534 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002535 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002536 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002537
2538 # add missed & remove other
2539 $TypeInfo{$Version} = \%AddTypes;
2540 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002541}
2542
2543sub addMissedTypes_Post()
2544{
2545 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2546 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002547 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2548 {
2549 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2550 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2551 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2552 }
2553 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002554 }
2555}
2556
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002557sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002558{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002559 my $TypeId = $_[0];
2560 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2561 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002562 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002563 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002564 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002565}
2566
2567sub getArraySize($$)
2568{
2569 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002570 if(my $Size = getSize($TypeId))
2571 {
2572 my $Elems = $Size/$BYTE_SIZE;
2573 while($BaseName=~s/\s*\[(\d+)\]//) {
2574 $Elems/=$1;
2575 }
2576 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2577 {
2578 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2579 $Elems/=$BasicSize;
2580 }
2581 }
2582 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002583 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002584 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002585}
2586
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002587sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002588{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002589 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002590 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002591 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2592 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002593 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002594 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2595 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2596 if(not $NodeType)
2597 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002598 return ();
2599 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002600 if($NodeType eq "tree_vec")
2601 {
2602 if($Pos!=$#Positions)
2603 { # select last vector of parameters ( ns<P1>::type<P2> )
2604 next;
2605 }
2606 }
2607 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2608 foreach my $P (@Params)
2609 {
2610 if($P eq "") {
2611 return ();
2612 }
2613 elsif($P ne "\@skip\@") {
2614 @TmplParams = (@TmplParams, $P);
2615 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002616 }
2617 }
2618 return @TmplParams;
2619}
2620
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002621sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002622{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002623 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002624 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002625 if(defined $TypeInfo{$Version}{$TypeId}
2626 and $TypeInfo{$Version}{$TypeId}{"Name"})
2627 { # already created
2628 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002629 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002630 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2631 { # incomplete type
2632 return ();
2633 }
2634 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2635
2636 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002637 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002638
2639 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2640 {
2641 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2642 {
2643 if($Info=~/qual[ ]*:/)
2644 {
2645 if(my $NID = ++$MAX_ID)
2646 {
2647 $MissedBase{$Version}{$TypeId}="$NID";
2648 $MissedBase_R{$Version}{$NID}=$TypeId;
2649 $LibInfo{$Version}{"info"}{$NID} = $LibInfo{$Version}{"info"}{$TypeId};
2650 $LibInfo{$Version}{"info_type"}{$NID} = $LibInfo{$Version}{"info_type"}{$TypeId};
2651 }
2652 }
2653 }
2654 $TypeAttr{"Type"} = "Typedef";
2655 }
2656 else {
2657 $TypeAttr{"Type"} = getTypeType($TypeId);
2658 }
2659
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002660 if($TypeAttr{"Type"} eq "Unknown") {
2661 return ();
2662 }
2663 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2664 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002665 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002666 if(my $TName = $TypeAttr{"Name"})
2667 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002668 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002669 $TName_Tid{$Version}{$TName} = $TypeId;
2670 return %TypeAttr;
2671 }
2672 else {
2673 return ();
2674 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002675 }
2676 elsif($TypeAttr{"Type"} eq "Array")
2677 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002678 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2679 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002680 return ();
2681 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002682 if(my $Algn = getAlgn($TypeId)) {
2683 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2684 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002685 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002686 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002687 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002688 if(not $BTAttr{"Name"}) {
2689 return ();
2690 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002691 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002692 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002693 if(my $Size = getSize($TypeId)) {
2694 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2695 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002696 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002697 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2698 }
2699 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002700 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002701 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002702 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002703 else
2704 {
2705 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002706 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002707 $TypeAttr{"Name"} = $1."[]".$2;
2708 }
2709 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002710 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002711 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002712 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002713 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002714 if($BTAttr{"Header"}) {
2715 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002716 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002717 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002718 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2719 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002720 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002721 return ();
2722 }
2723 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
2724 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002725 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002726 if($TypeAttr{"Name"})
2727 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002728 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2729 if($TypeAttr{"Name"} ne "int" or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002730 { # NOTE: register only one int: with built-in decl
2731 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2732 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2733 }
2734 }
2735 return %TypeAttr;
2736 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002737 else {
2738 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002739 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002740 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002741 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002742 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002743 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2744 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002745 return ();
2746 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002747 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002748 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002749 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002750 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002751 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002752 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002753 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002754 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002755 }
2756 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002757 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002758 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002759 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002760 return ();
2761 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002762 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002763 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002764 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002765 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002766 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002767 }
2768 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002769 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002770 {
2771 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002772 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002773 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002774 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002775 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
2776 }
2777 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002778 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002779 }
2780 }
2781 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002782 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002783 }
2784 if($TypeAttr{"Type"} eq "Typedef")
2785 {
2786 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002787
2788 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
2789 return ();
2790 }
2791
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002792 if(isAnon($TypeAttr{"Name"}))
2793 { # anon typedef to anon type: ._N
2794 return ();
2795 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002796
2797 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
2798 { # artificial typedef of "struct X" to "X"
2799 $TypeAttr{"Artificial"} = 1;
2800 }
2801
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002802 if(my $NS = getNameSpace($TypeDeclId))
2803 {
2804 my $TypeName = $TypeAttr{"Name"};
2805 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
2806 { # "some_type" is the typedef to "struct some_type" in C++
2807 if($3) {
2808 $TypeAttr{"Name"} = $3."::".$TypeName;
2809 }
2810 }
2811 else
2812 {
2813 $TypeAttr{"NameSpace"} = $NS;
2814 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002815
2816 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
2817 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
2818 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002819 if($BTAttr{"NameSpace"}
2820 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002821 { # types like "std::fpos<__mbstate_t>" are
2822 # not covered by typedefs in the TU dump
2823 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002824 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2825 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002826 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002827 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002828 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002829 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002830 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002831 }
2832 }
2833 }
2834 }
2835 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002836 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002837 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002838 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002839 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
2840 { # typedef int*const TYPEDEF; // first
2841 # int foo(TYPEDEF p); // const is optimized out
2842 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
2843 if($BTAttr{"Name"}=~/</)
2844 {
2845 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
2846 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
2847 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002848 }
2849 }
2850 }
2851 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
2852 }
2853 if(not $TypeAttr{"Size"})
2854 {
2855 if($TypeAttr{"Type"} eq "Pointer") {
2856 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
2857 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002858 elsif($BTAttr{"Size"}) {
2859 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002860 }
2861 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002862 if(my $Algn = getAlgn($TypeId)) {
2863 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2864 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002865 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002866 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
2867 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002868 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002869 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002870 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002871 { # typedef to "class Class"
2872 # should not be registered in TName_Tid
2873 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2874 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2875 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002876 }
2877 return %TypeAttr;
2878 }
2879}
2880
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002881sub getTreeVec($)
2882{
2883 my %Vector = ();
2884 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2885 {
2886 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2887 { # string length is N-1 because of the null terminator
2888 $Vector{$1} = $2;
2889 }
2890 }
2891 return \%Vector;
2892}
2893
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002894sub get_TemplateParam($$)
2895{
2896 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002897 return () if(not $Type_Id);
2898 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
2899 return () if(not $NodeType);
2900 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002901 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002902 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002903 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002904 my $Num = getNodeIntCst($Type_Id);
2905 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002906 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002907 }
2908 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002909 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002910 }
2911 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002912 elsif($NodeType eq "string_cst") {
2913 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002914 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002915 elsif($NodeType eq "tree_vec")
2916 {
2917 my $Vector = getTreeVec($Type_Id);
2918 my @Params = ();
2919 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
2920 {
2921 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
2922 push(@Params, $P2);
2923 }
2924 }
2925 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002926 }
2927 else
2928 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002929 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002930 my $PName = $ParamAttr{"Name"};
2931 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002932 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002933 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002934 if($PName=~/\>/)
2935 {
2936 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002937 $PName = $Cover;
2938 }
2939 }
2940 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04002941 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002942 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
2943 # template<typename _Key, typename _Compare = std::less<_Key>
2944 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
2945 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
2946 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
2947 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002948 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002949 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002950 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002951 }
2952}
2953
2954sub cover_stdcxx_typedef($)
2955{
2956 my $TypeName = $_[0];
2957 if(my @Covers = sort {length($a)<=>length($b)}
2958 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
2959 { # take the shortest typedef
2960 # FIXME: there may be more than
2961 # one typedefs to the same type
2962 return $Covers[0];
2963 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002964 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002965 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
2966 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
2967 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002968 if(my $Cover = $Covers[0])
2969 {
2970 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
2971 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
2972 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002973 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002974 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002975}
2976
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002977sub getNodeIntCst($)
2978{
2979 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002980 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002981 if($EnumMembName_Id{$Version}{$CstId}) {
2982 return $EnumMembName_Id{$Version}{$CstId};
2983 }
2984 elsif((my $Value = getTreeValue($CstId)) ne "")
2985 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002986 if($Value eq "0")
2987 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002988 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002989 return "false";
2990 }
2991 else {
2992 return "0";
2993 }
2994 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002995 elsif($Value eq "1")
2996 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002997 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002998 return "true";
2999 }
3000 else {
3001 return "1";
3002 }
3003 }
3004 else {
3005 return $Value;
3006 }
3007 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003008 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003009}
3010
3011sub getNodeStrCst($)
3012{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003013 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3014 {
3015 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003016 {
3017 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3018 { # string length is N-1 because of the null terminator
3019 return substr($1, 0, $2-1);
3020 }
3021 else
3022 { # identifier_node
3023 return substr($1, 0, $2);
3024 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003025 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003026 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003027 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003028}
3029
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003030sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003031{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003032 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003033 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3034 if($Type eq "FieldPtr") {
3035 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3036 }
3037 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3038 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003039 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003040 if($Type eq "MethodPtr")
3041 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003042 if(my $Size = getSize($TypeId))
3043 {
3044 $Size/=$BYTE_SIZE;
3045 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003046 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003047 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003048 if(my $Algn = getAlgn($TypeId)) {
3049 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3050 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003051 # Return
3052 if($Type eq "FieldPtr")
3053 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003054 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003055 if($ReturnAttr{"Name"}) {
3056 $MemPtrName .= $ReturnAttr{"Name"};
3057 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003058 $TypeAttr{"Return"} = $PtrId;
3059 }
3060 else
3061 {
3062 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3063 {
3064 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003065 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3066 if(not $ReturnAttr{"Name"})
3067 { # templates
3068 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003069 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003070 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003071 $TypeAttr{"Return"} = $ReturnTypeId;
3072 }
3073 }
3074 # Class
3075 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3076 {
3077 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003078 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003079 if($Class{"Name"}) {
3080 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3081 }
3082 else {
3083 $MemPtrName .= " (*)";
3084 }
3085 }
3086 else {
3087 $MemPtrName .= " (*)";
3088 }
3089 # Parameters
3090 if($Type eq "FuncPtr"
3091 or $Type eq "MethodPtr")
3092 {
3093 my @ParamTypeName = ();
3094 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3095 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003096 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003097 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003098 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003099 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003100 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3101 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003102 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003103 my $PTypeId = $1;
3104 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003105 if(not $ParamAttr{"Name"})
3106 { # templates (template_type_parm), etc.
3107 return ();
3108 }
3109 if($ParamAttr{"Name"} eq "void") {
3110 last;
3111 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003112 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003113 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003114 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003115 push(@ParamTypeName, $ParamAttr{"Name"});
3116 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003117 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3118 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003119 }
3120 else {
3121 last;
3122 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003123 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003124 else {
3125 last;
3126 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003127 }
3128 }
3129 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3130 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003131 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003132 return %TypeAttr;
3133}
3134
3135sub getTreeTypeName($)
3136{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003137 my $TypeId = $_[0];
3138 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003139 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003140 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003141 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003142 if(my $Name = getNameByInfo($TypeId))
3143 { # bit_size_type
3144 return $Name;
3145 }
3146 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003147 return "unsigned int";
3148 }
3149 else {
3150 return "int";
3151 }
3152 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003153 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003154 return getNameByInfo($1);
3155 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003156 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003157 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003158}
3159
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003160sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003161{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003162 my $Ptd = pointTo($_[0]);
3163 return 0 if(not $Ptd);
3164 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003165 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003166 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3167 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003168 }
3169 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003170 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3171 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003172 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003173 if($InfoT1 eq "pointer_type"
3174 and $InfoT2 eq "function_type") {
3175 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003176 }
3177 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003178 return 0;
3179}
3180
3181sub isMethodPtr($)
3182{
3183 my $Ptd = pointTo($_[0]);
3184 return 0 if(not $Ptd);
3185 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3186 {
3187 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3188 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3189 and $Info=~/ ptrmem /) {
3190 return 1;
3191 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003192 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003193 return 0;
3194}
3195
3196sub isFieldPtr($)
3197{
3198 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3199 {
3200 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3201 and $Info=~/ ptrmem /) {
3202 return 1;
3203 }
3204 }
3205 return 0;
3206}
3207
3208sub pointTo($)
3209{
3210 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3211 {
3212 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3213 return $1;
3214 }
3215 }
3216 return "";
3217}
3218
3219sub getTypeTypeByTypeId($)
3220{
3221 my $TypeId = $_[0];
3222 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3223 {
3224 my $NType = $NodeType{$TType};
3225 if($NType eq "Intrinsic") {
3226 return $NType;
3227 }
3228 elsif(isFuncPtr($TypeId)) {
3229 return "FuncPtr";
3230 }
3231 elsif(isMethodPtr($TypeId)) {
3232 return "MethodPtr";
3233 }
3234 elsif(isFieldPtr($TypeId)) {
3235 return "FieldPtr";
3236 }
3237 elsif($NType ne "Other") {
3238 return $NType;
3239 }
3240 }
3241 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003242}
3243
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003244my %UnQual = (
3245 "r"=>"restrict",
3246 "v"=>"volatile",
3247 "c"=>"const",
3248 "cv"=>"const volatile"
3249);
3250
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003251sub getQual($)
3252{
3253 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003254 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3255 {
3256 my ($Qual, $To) = ();
3257 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3258 $Qual = $UnQual{$1};
3259 }
3260 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3261 $To = $1;
3262 }
3263 if($Qual and $To) {
3264 return ($Qual, $To);
3265 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003266 }
3267 return ();
3268}
3269
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003270sub getQualType($)
3271{
3272 if($_[0] eq "const volatile") {
3273 return "ConstVolatile";
3274 }
3275 return ucfirst($_[0]);
3276}
3277
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003278sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003279{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003280 my $TypeId = $_[0];
3281 my $TypeDeclId = getTypeDeclId($TypeId);
3282 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003283 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003284 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3285 return "Typedef";
3286 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003287 }
3288 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3289 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003290 if(($Qual or $To) and $TypeDeclId
3291 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003292 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003293 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003294 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003295 elsif(not $MissedBase_R{$Version}{$TypeId}
3296 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003297 return "Typedef";
3298 }
3299 elsif($Qual)
3300 { # qualified types
3301 return getQualType($Qual);
3302 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003303
3304 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3305 { # typedef struct { ... } name
3306 $TypeTypedef{$Version}{$TypeId} = $1;
3307 }
3308
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003309 my $TypeType = getTypeTypeByTypeId($TypeId);
3310 if($TypeType eq "Struct")
3311 {
3312 if($TypeDeclId
3313 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3314 return "Template";
3315 }
3316 }
3317 return $TypeType;
3318}
3319
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003320sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003321{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003322 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3323 {
3324 my $TDid = getTypeDeclId($_[0]);
3325 if(getNameByInfo($TDid)
3326 and $Info=~/unql[ ]*:[ ]*\@(\d+) /
3327 and getTypeId($TDid) eq $_[0]) {
3328 return $1;
3329 }
3330 }
3331 return 0;
3332}
3333
3334sub selectBaseType($)
3335{
3336 my $TypeId = $_[0];
3337 if(defined $MissedTypedef{$Version}{$TypeId})
3338 { # add missed typedefs
3339 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3340 return ($TypeId, "");
3341 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003342 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003343 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3344 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003345
3346 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3347 my $MB = $MissedBase{$Version}{$TypeId};
3348
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003349 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003350 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003351 and (getTypeId($1) ne $TypeId)
3352 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003353 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003354 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003355 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003356 elsif($MB)
3357 { # add base
3358 return ($MB, "");
3359 }
3360 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003361 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003362 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003363 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003364 elsif($Qual or $To)
3365 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003366 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003367 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003368 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003369 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003370 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003371 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003372 }
3373 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003374 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003375 }
3376 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003377 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003378 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003379 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003380 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003381 }
3382 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003383 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003384 }
3385 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003386 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003387 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003388 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003389 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003390 }
3391 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003392 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003393 }
3394 }
3395 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003396 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003397 }
3398}
3399
3400sub getSymbolInfo_All()
3401{
3402 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3403 { # reverse order
3404 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003405 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003406 }
3407 }
3408}
3409
3410sub getVarInfo_All()
3411{
3412 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3413 { # reverse order
3414 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003415 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003416 }
3417 }
3418}
3419
3420sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003421 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003422}
3423
3424sub getVarInfo($)
3425{
3426 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003427 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003428 {
3429 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3430 if($NSInfoType and $NSInfoType eq "function_decl") {
3431 return;
3432 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003433 }
3434 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3435 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3436 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3437 delete($SymbolInfo{$Version}{$InfoId});
3438 return;
3439 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003440 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003441 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003442 delete($SymbolInfo{$Version}{$InfoId});
3443 return;
3444 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003445 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3446 delete($SymbolInfo{$Version}{$InfoId});
3447 return;
3448 }
3449 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003450 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3451 {
3452 if($OSgroup eq "windows")
3453 { # cut the offset
3454 $MnglName=~s/\@\d+\Z//g;
3455 }
3456 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3457 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003458 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003459 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003460 { # validate mangled name
3461 delete($SymbolInfo{$Version}{$InfoId});
3462 return;
3463 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003464 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003465 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003466 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003467 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003468 }
3469 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3470 { # non-public global data
3471 delete($SymbolInfo{$Version}{$InfoId});
3472 return;
3473 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003474 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003475 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003476 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003477 if(not $TypeInfo{$Version}{$Rid}{"Name"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003478 { # typename_type
3479 delete($SymbolInfo{$Version}{$InfoId});
3480 return;
3481 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003482 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3483 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003484 if(defined $Val) {
3485 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3486 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003487 }
3488 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003489 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3490 {
3491 if(not $TypeInfo{$Version}{$ClassId}{"Name"})
3492 { # templates
3493 delete($SymbolInfo{$Version}{$InfoId});
3494 return;
3495 }
3496 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003497 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3498 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003499 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003500 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003501 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003502 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003503 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003504 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003505 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003506 if(not $CheckHeadersOnly)
3507 {
3508 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3509 {
3510 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3511 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3512 {
3513 if(link_symbol($ShortName, $Version, "-Deps"))
3514 { # "const" global data is mangled as _ZL... in the TU dump
3515 # but not mangled when compiling a C shared library
3516 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3517 }
3518 }
3519 }
3520 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003521 if($COMMON_LANGUAGE{$Version} eq "C++")
3522 {
3523 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3524 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003525 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003526 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3527 }
3528 }
3529 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3530 { # try to mangle symbol (link with libraries)
3531 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3532 }
3533 if($OStarget eq "windows")
3534 {
3535 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3536 { # link MS C++ symbols from library with GCC symbols from headers
3537 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3538 }
3539 }
3540 }
3541 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3542 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3543 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003544 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3545 {
3546 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3547 { # non-target symbols
3548 delete($SymbolInfo{$Version}{$InfoId});
3549 return;
3550 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003551 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003552 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3553 {
3554 if(defined $MissedTypedef{$Version}{$Rid})
3555 {
3556 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3557 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3558 }
3559 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003560 }
3561 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003562 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003563 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3564 }
3565 if($ShortName=~/\A(_Z|\?)/) {
3566 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3567 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003568
3569 if($ExtraDump) {
3570 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3571 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003572}
3573
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003574sub isConstType($$)
3575{
3576 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003577 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003578 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003579 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003580 }
3581 return ($Base{"Type"} eq "Const");
3582}
3583
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003584sub getTrivialName($$)
3585{
3586 my ($TypeInfoId, $TypeId) = @_;
3587 my %TypeAttr = ();
3588 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3589 if(not $TypeAttr{"Name"}) {
3590 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3591 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003592 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003593 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003594 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003595 if(isAnon($TypeAttr{"Name"}))
3596 {
3597 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003598 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003599 { # searching for a first not anon scope
3600 if($NSId eq $NameSpaceId) {
3601 last;
3602 }
3603 else
3604 {
3605 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3606 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003607 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003608 last;
3609 }
3610 }
3611 $NameSpaceId=$NSId;
3612 }
3613 }
3614 else
3615 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003616 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003617 {
3618 if($NameSpaceId ne $TypeId) {
3619 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3620 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003621 }
3622 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003623 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003624 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3625 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003626 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003627 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003628 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003629 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003630 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003631 if($TypeAttr{"NameSpace"}) {
3632 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3633 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003634 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003635 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3636 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003637 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003638 my @TParams = getTParams($TypeId, "Type");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003639 if(not @TParams)
3640 { # template declarations with abstract params
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003641 return ("", "");
3642 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003643 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003644 }
3645 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3646}
3647
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003648sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003649{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003650 my $TypeId = $_[0];
3651 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003652
3653 if($TemplateDecl{$Version}{$TypeId})
3654 { # template_decl
3655 return ();
3656 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003657 if(my $ScopeId = getTreeAttr_Scpe($TypeInfoId))
3658 {
3659 if($TemplateDecl{$Version}{$ScopeId})
3660 { # template_decl
3661 return ();
3662 }
3663 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003664
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003665 my %TypeAttr = ();
3666 if(getTypeTypeByTypeId($TypeId)!~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/) {
3667 return ();
3668 }
3669 setTypeAccess($TypeId, \%TypeAttr);
3670 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3671 if(isBuiltIn($TypeAttr{"Header"}))
3672 {
3673 delete($TypeAttr{"Header"});
3674 delete($TypeAttr{"Line"});
3675 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003676 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003677 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3678 if(not $TypeAttr{"Name"}) {
3679 return ();
3680 }
3681 if(not $TypeAttr{"NameSpace"}) {
3682 delete($TypeAttr{"NameSpace"});
3683 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003684 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003685 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003686 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003687 {
3688 foreach my $Pos (0 .. $#TParams) {
3689 $TypeAttr{"TParam"}{$Pos}{"name"}=$TParams[$Pos];
3690 }
3691 }
3692 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003693 if(my $Size = getSize($TypeId))
3694 {
3695 $Size = $Size/$BYTE_SIZE;
3696 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003697 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003698 else
3699 { # declaration only
3700 $TypeAttr{"Forward"} = 1;
3701 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003702
3703 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
3704
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003705 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003706 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003707 {
3708 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003709 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003710 }
3711 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003712 or $TypeAttr{"Type"} eq "Class")
3713 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003714 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003715 if($Skip) {
3716 return ();
3717 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003718 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003719 if(my $Algn = getAlgn($TypeId)) {
3720 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3721 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003722 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003723
3724 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
3725 {
3726 if(not $TypedefToAnon{$TypeId}
3727 and not keys(%{$TemplateInstance{$Version}{"Type"}{$TypeId}}))
3728 {
3729 if(not isAnon($TypeAttr{"Name"})) {
3730 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
3731 }
3732 }
3733 }
3734
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003735 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003736 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
3737 {
3738 my @Entries = split(/\n/, $VTable);
3739 foreach (1 .. $#Entries)
3740 {
3741 my $Entry = $Entries[$_];
3742 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
3743 $TypeAttr{"VTable"}{$1} = $2;
3744 }
3745 }
3746 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04003747
3748 if($TypeAttr{"Type"} eq "Enum")
3749 {
3750 if(not $TypeAttr{"NameSpace"})
3751 {
3752 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
3753 {
3754 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003755 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04003756 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003757 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04003758 "Header"=>$TypeAttr{"Header"}
3759 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003760 if(isAnon($TypeAttr{"Name"}))
3761 {
3762 %{$Constants{$Version}{$MName}} = (
3763 "Value" => $MVal,
3764 "Header" => $TypeAttr{"Header"}
3765 );
3766 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04003767 }
3768 }
3769 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003770 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003771 {
3772 if(defined $TypedefToAnon{$TypeId}) {
3773 $TypeAttr{"AnonTypedef"} = 1;
3774 }
3775 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04003776
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003777 return %TypeAttr;
3778}
3779
3780sub detect_lang($)
3781{
3782 my $TypeId = $_[0];
3783 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003784 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003785 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003786 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
3787 }
3788 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003789 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003790 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003791 while($Fncs)
3792 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003793 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003794 return 1;
3795 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003796 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003797 }
3798 }
3799 return 0;
3800}
3801
3802sub setSpec($$)
3803{
3804 my ($TypeId, $TypeAttr) = @_;
3805 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3806 if($Info=~/\s+spec\s+/) {
3807 $TypeAttr->{"Spec"} = 1;
3808 }
3809}
3810
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003811sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003812{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003813 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003814 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3815 if($Info=~/binf[ ]*:[ ]*@(\d+) /)
3816 {
3817 $Info = $LibInfo{$Version}{"info"}{$1};
3818 my $Pos = 0;
3819 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
3820 {
3821 my ($Access, $BInfoId) = ($1, $2);
3822 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003823 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
3824 if(not $CType or $CType eq "template_type_parm"
3825 or $CType eq "typename_type")
3826 { # skip
3827 return 1;
3828 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003829 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003830 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003831 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
3832 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003833 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003834 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
3835 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003836 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003837 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003838 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003839 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
3840 }
3841 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003842 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003843 }
3844 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003845 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003846}
3847
3848sub getBinfClassId($)
3849{
3850 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
3851 $Info=~/type[ ]*:[ ]*@(\d+) /;
3852 return $1;
3853}
3854
3855sub unmangledFormat($$)
3856{
3857 my ($Name, $LibVersion) = @_;
3858 $Name = uncover_typedefs($Name, $LibVersion);
3859 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
3860 $Name=~s/\(\w+\)(\d)/$1/;
3861 return $Name;
3862}
3863
3864sub modelUnmangled($$)
3865{
3866 my ($InfoId, $Compiler) = @_;
3867 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
3868 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
3869 }
3870 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
3871 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
3872 $PureSignature = "~".$PureSignature;
3873 }
3874 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
3875 {
3876 my (@Params, @ParamTypes) = ();
3877 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
3878 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
3879 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
3880 }
3881 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
3882 { # checking parameters
3883 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003884 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003885 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003886 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003887 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003888 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003889 }
3890 @ParamTypes = (@ParamTypes, $PTName);
3891 }
3892 if(@ParamTypes) {
3893 $PureSignature .= "(".join(", ", @ParamTypes).")";
3894 }
3895 else
3896 {
3897 if($Compiler eq "MSVC")
3898 {
3899 $PureSignature .= "(void)";
3900 }
3901 else
3902 { # GCC
3903 $PureSignature .= "()";
3904 }
3905 }
3906 $PureSignature = delete_keywords($PureSignature);
3907 }
3908 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3909 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003910 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003911 $PureSignature = $ClassName."::".$PureSignature;
3912 }
3913 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
3914 $PureSignature = $NS."::".$PureSignature;
3915 }
3916 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
3917 $PureSignature .= " const";
3918 }
3919 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
3920 $PureSignature .= " volatile";
3921 }
3922 my $ShowReturn = 0;
3923 if($Compiler eq "MSVC"
3924 and $SymbolInfo{$Version}{$InfoId}{"Data"})
3925 {
3926 $ShowReturn=1;
3927 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003928 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
3929 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003930 {
3931 $ShowReturn=1;
3932 }
3933 if($ShowReturn)
3934 { # mangled names for template function specializations include return value
3935 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
3936 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003937 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003938 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
3939 $PureSignature = $ReturnName." ".$PureSignature;
3940 }
3941 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003942 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003943}
3944
3945sub mangle_symbol($$$)
3946{ # mangling for simple methods
3947 # see gcc-4.6.0/gcc/cp/mangle.c
3948 my ($InfoId, $LibVersion, $Compiler) = @_;
3949 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
3950 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
3951 }
3952 my $Mangled = "";
3953 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003954 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003955 }
3956 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003957 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003958 }
3959 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
3960}
3961
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003962sub mangle_symbol_MSVC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003963{
3964 my ($InfoId, $LibVersion) = @_;
3965 return "";
3966}
3967
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003968sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003969{ # see gcc-4.6.0/gcc/cp/mangle.c
3970 my ($InfoId, $LibVersion) = @_;
3971 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003972 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003973 my %Repl = ();# SN_ replacements
3974 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
3975 {
3976 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
3977 if($MangledClass!~/\AN/) {
3978 $MangledClass = "N".$MangledClass;
3979 }
3980 else {
3981 $MangledClass=~s/E\Z//;
3982 }
3983 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
3984 $MangledClass=~s/\AN/NV/;
3985 }
3986 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
3987 $MangledClass=~s/\AN/NK/;
3988 }
3989 $Mangled .= $MangledClass;
3990 }
3991 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
3992 { # mangled by name due to the absence of structured info
3993 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
3994 if($MangledNS!~/\AN/) {
3995 $MangledNS = "N".$MangledNS;
3996 }
3997 else {
3998 $MangledNS=~s/E\Z//;
3999 }
4000 $Mangled .= $MangledNS;
4001 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004002 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004003 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004004 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004005 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004006 foreach (@TPos) {
4007 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4008 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004009 }
4010 elsif($TmplParams)
4011 { # remangling mode
4012 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004013 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004014 }
4015 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4016 $Mangled .= "C1";
4017 }
4018 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4019 $Mangled .= "D0";
4020 }
4021 elsif($ShortName)
4022 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004023 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4024 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004025 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004026 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004027 { # "const" global data is mangled as _ZL...
4028 $Mangled .= "L";
4029 }
4030 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004031 if($ShortName=~/\Aoperator(\W.*)\Z/)
4032 {
4033 my $Op = $1;
4034 $Op=~s/\A[ ]+//g;
4035 if(my $OpMngl = $OperatorMangling{$Op}) {
4036 $Mangled .= $OpMngl;
4037 }
4038 else { # conversion operator
4039 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4040 }
4041 }
4042 else {
4043 $Mangled .= length($ShortName).$ShortName;
4044 }
4045 if(@TParams)
4046 { # templates
4047 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004048 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004049 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4050 }
4051 $Mangled .= "E";
4052 }
4053 if(not $ClassId and @TParams) {
4054 add_substitution($ShortName, \%Repl, 0);
4055 }
4056 }
4057 if($ClassId or $NameSpace) {
4058 $Mangled .= "E";
4059 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004060 if(@TParams)
4061 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004062 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004063 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4064 }
4065 }
4066 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4067 {
4068 my @Params = ();
4069 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4070 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4071 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4072 }
4073 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4074 { # checking parameters
4075 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4076 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4077 }
4078 if(not @Params) {
4079 $Mangled .= "v";
4080 }
4081 }
4082 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4083 $Mangled = write_stdcxx_substitution($Mangled);
4084 if($Mangled eq "_Z") {
4085 return "";
4086 }
4087 return $Mangled;
4088}
4089
4090sub correct_incharge($$$)
4091{
4092 my ($InfoId, $LibVersion, $Mangled) = @_;
4093 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4094 {
4095 if($MangledNames{$LibVersion}{$Mangled}) {
4096 $Mangled=~s/C1E/C2E/;
4097 }
4098 }
4099 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4100 {
4101 if($MangledNames{$LibVersion}{$Mangled}) {
4102 $Mangled=~s/D0E/D1E/;
4103 }
4104 if($MangledNames{$LibVersion}{$Mangled}) {
4105 $Mangled=~s/D1E/D2E/;
4106 }
4107 }
4108 return $Mangled;
4109}
4110
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004111sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004112{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004113 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004114 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004115 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004116 return $Name;
4117 }
4118 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004119 while(my $CPos = find_center($TParams, "<"))
4120 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004121 $TParams = substr($TParams, $CPos);
4122 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004123 if($TParams=~s/\A<(.+)>\Z/$1/) {
4124 $Name=~s/<\Q$TParams\E>\Z//;
4125 }
4126 else
4127 { # error
4128 $TParams = "";
4129 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004130 return ($Name, $TParams);
4131}
4132
4133sub get_sub_ns($)
4134{
4135 my $Name = $_[0];
4136 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004137 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004138 {
4139 push(@NS, substr($Name, 0, $CPos));
4140 $Name = substr($Name, $CPos);
4141 $Name=~s/\A:://;
4142 }
4143 return (join("::", @NS), $Name);
4144}
4145
4146sub mangle_ns($$$)
4147{
4148 my ($Name, $LibVersion, $Repl) = @_;
4149 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4150 {
4151 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4152 $Mangled=~s/\AN(.+)E\Z/$1/;
4153 return $Mangled;
4154
4155 }
4156 else
4157 {
4158 my ($MangledNS, $SubNS) = ("", "");
4159 ($SubNS, $Name) = get_sub_ns($Name);
4160 if($SubNS) {
4161 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4162 }
4163 $MangledNS .= length($Name).$Name;
4164 add_substitution($MangledNS, $Repl, 0);
4165 return $MangledNS;
4166 }
4167}
4168
4169sub mangle_param($$$)
4170{
4171 my ($PTid, $LibVersion, $Repl) = @_;
4172 my ($MPrefix, $Mangled) = ("", "");
4173 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004174 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004175 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004176 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004177 if(not $BaseType_Name) {
4178 return "";
4179 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004180 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004181 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004182 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4183 while($Suffix=~/(&|\*|const)\Z/)
4184 {
4185 if($Suffix=~s/[ ]*&\Z//) {
4186 $MPrefix .= "R";
4187 }
4188 if($Suffix=~s/[ ]*\*\Z//) {
4189 $MPrefix .= "P";
4190 }
4191 if($Suffix=~s/[ ]*const\Z//)
4192 {
4193 if($MPrefix=~/R|P/
4194 or $Suffix=~/&|\*/) {
4195 $MPrefix .= "K";
4196 }
4197 }
4198 if($Suffix=~s/[ ]*volatile\Z//) {
4199 $MPrefix .= "V";
4200 }
4201 #if($Suffix=~s/[ ]*restrict\Z//) {
4202 #$MPrefix .= "r";
4203 #}
4204 }
4205 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4206 $Mangled .= $Token;
4207 }
4208 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4209 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004210 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004211 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004212 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004213 foreach (@TPos) {
4214 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4215 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004216 }
4217 elsif($TmplParams)
4218 { # remangling mode
4219 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004220 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004221 }
4222 my $MangledNS = "";
4223 my ($SubNS, $SName) = get_sub_ns($ShortName);
4224 if($SubNS) {
4225 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4226 }
4227 $MangledNS .= length($SName).$SName;
4228 if(@TParams) {
4229 add_substitution($MangledNS, $Repl, 0);
4230 }
4231 $Mangled .= "N".$MangledNS;
4232 if(@TParams)
4233 { # templates
4234 $Mangled .= "I";
4235 foreach my $TParam (@TParams) {
4236 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4237 }
4238 $Mangled .= "E";
4239 }
4240 $Mangled .= "E";
4241 }
4242 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4243 {
4244 if($BaseType{"Type"} eq "MethodPtr") {
4245 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4246 }
4247 else {
4248 $Mangled .= "PF";
4249 }
4250 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4251 my @Params = keys(%{$BaseType{"Param"}});
4252 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4253 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4254 }
4255 if(not @Params) {
4256 $Mangled .= "v";
4257 }
4258 $Mangled .= "E";
4259 }
4260 elsif($BaseType{"Type"} eq "FieldPtr")
4261 {
4262 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4263 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4264 }
4265 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4266 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4267 {
4268 if($Mangled eq $Optimized)
4269 {
4270 if($ShortName!~/::/)
4271 { # remove "N ... E"
4272 if($MPrefix) {
4273 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4274 }
4275 else {
4276 $Mangled=~s/\AN(.+)E\Z/$1/g;
4277 }
4278 }
4279 }
4280 else {
4281 $Mangled = $Optimized;
4282 }
4283 }
4284 add_substitution($Mangled, $Repl, 1);
4285 return $Mangled;
4286}
4287
4288sub mangle_template_param($$$)
4289{ # types + literals
4290 my ($TParam, $LibVersion, $Repl) = @_;
4291 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4292 return mangle_param($TPTid, $LibVersion, $Repl);
4293 }
4294 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4295 { # class_name<1u>::method(...)
4296 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4297 }
4298 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4299 { # class_name<(signed char)1>::method(...)
4300 return "L".$IntrinsicMangling{$1}.$2."E";
4301 }
4302 elsif($TParam eq "true")
4303 { # class_name<true>::method(...)
4304 return "Lb1E";
4305 }
4306 elsif($TParam eq "false")
4307 { # class_name<true>::method(...)
4308 return "Lb0E";
4309 }
4310 else { # internal error
4311 return length($TParam).$TParam;
4312 }
4313}
4314
4315sub add_substitution($$$)
4316{
4317 my ($Value, $Repl, $Rec) = @_;
4318 if($Rec)
4319 { # subtypes
4320 my @Subs = ($Value);
4321 while($Value=~s/\A(R|P|K)//) {
4322 push(@Subs, $Value);
4323 }
4324 foreach (reverse(@Subs)) {
4325 add_substitution($_, $Repl, 0);
4326 }
4327 return;
4328 }
4329 return if($Value=~/\AS(\d*)_\Z/);
4330 $Value=~s/\AN(.+)E\Z/$1/g;
4331 return if(defined $Repl->{$Value});
4332 return if(length($Value)<=1);
4333 return if($StdcxxMangling{$Value});
4334 # check for duplicates
4335 my $Base = $Value;
4336 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4337 {
4338 my $Num = $Repl->{$Type};
4339 my $Replace = macro_mangle($Num);
4340 $Base=~s/\Q$Replace\E/$Type/;
4341 }
4342 if(my $OldNum = $Repl->{$Base})
4343 {
4344 $Repl->{$Value} = $OldNum;
4345 return;
4346 }
4347 my @Repls = sort {$b<=>$a} values(%{$Repl});
4348 if(@Repls) {
4349 $Repl->{$Value} = $Repls[0]+1;
4350 }
4351 else {
4352 $Repl->{$Value} = -1;
4353 }
4354 # register duplicates
4355 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004356 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004357 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4358 {
4359 next if($Base eq $Type);
4360 my $Num = $Repl->{$Type};
4361 my $Replace = macro_mangle($Num);
4362 $Base=~s/\Q$Type\E/$Replace/;
4363 $Repl->{$Base} = $Repl->{$Value};
4364 }
4365}
4366
4367sub macro_mangle($)
4368{
4369 my $Num = $_[0];
4370 if($Num==-1) {
4371 return "S_";
4372 }
4373 else
4374 {
4375 my $Code = "";
4376 if($Num<10)
4377 { # S0_, S1_, S2_, ...
4378 $Code = $Num;
4379 }
4380 elsif($Num>=10 and $Num<=35)
4381 { # SA_, SB_, SC_, ...
4382 $Code = chr(55+$Num);
4383 }
4384 else
4385 { # S10_, S11_, S12_
4386 $Code = $Num-26; # 26 is length of english alphabet
4387 }
4388 return "S".$Code."_";
4389 }
4390}
4391
4392sub write_stdcxx_substitution($)
4393{
4394 my $Mangled = $_[0];
4395 if($StdcxxMangling{$Mangled}) {
4396 return $StdcxxMangling{$Mangled};
4397 }
4398 else
4399 {
4400 my @Repls = keys(%StdcxxMangling);
4401 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4402 foreach my $MangledType (@Repls)
4403 {
4404 my $Replace = $StdcxxMangling{$MangledType};
4405 #if($Mangled!~/$Replace/) {
4406 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4407 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4408 #}
4409 }
4410 }
4411 return $Mangled;
4412}
4413
4414sub write_substitution($$)
4415{
4416 my ($Mangled, $Repl) = @_;
4417 if(defined $Repl->{$Mangled}
4418 and my $MnglNum = $Repl->{$Mangled}) {
4419 $Mangled = macro_mangle($MnglNum);
4420 }
4421 else
4422 {
4423 my @Repls = keys(%{$Repl});
4424 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4425 # FIXME: how to apply replacements? by num or by pos
4426 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4427 foreach my $MangledType (@Repls)
4428 {
4429 my $Replace = macro_mangle($Repl->{$MangledType});
4430 if($Mangled!~/$Replace/) {
4431 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4432 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4433 }
4434 }
4435 }
4436 return $Mangled;
4437}
4438
4439sub delete_keywords($)
4440{
4441 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004442 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004443 return $TypeName;
4444}
4445
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004446sub uncover_typedefs($$)
4447{
4448 my ($TypeName, $LibVersion) = @_;
4449 return "" if(not $TypeName);
4450 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4451 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4452 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004453 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004454 while($TypeName_New ne $TypeName_Pre)
4455 {
4456 $TypeName_Pre = $TypeName_New;
4457 my $TypeName_Copy = $TypeName_New;
4458 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004459 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004460 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004461 if(not $Intrinsic_Keywords{$1}) {
4462 $Words{$1} = 1;
4463 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004464 }
4465 foreach my $Word (keys(%Words))
4466 {
4467 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4468 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004469 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004470 if($BaseType_Name=~/\([\*]+\)/)
4471 { # FuncPtr
4472 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4473 {
4474 my $Type_Suffix = $1;
4475 $TypeName_New = $BaseType_Name;
4476 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004477 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004478 }
4479 }
4480 }
4481 else
4482 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004483 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004484 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004485 }
4486 }
4487 }
4488 }
4489 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4490}
4491
4492sub isInternal($)
4493{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004494 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4495 {
4496 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4497 {
4498 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4499 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4500 return 1;
4501 }
4502 }
4503 }
4504 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004505}
4506
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004507sub getDataVal($$)
4508{
4509 my ($InfoId, $TypeId) = @_;
4510 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4511 {
4512 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4513 {
4514 if(defined $LibInfo{$Version}{"info_type"}{$1}
4515 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004516 {
4517 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004518 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004519 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4520 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004521 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004522 if(my $Addr = getTreeAttr_Op($1)) {
4523 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004524 }
4525 }
4526 }
4527 }
4528 else {
4529 return getInitVal($1, $TypeId);
4530 }
4531 }
4532 }
4533 return undef;
4534}
4535
4536sub getInitVal($$)
4537{
4538 my ($InfoId, $TypeId) = @_;
4539 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4540 {
4541 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4542 {
4543 if($InfoType eq "integer_cst")
4544 {
4545 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004546 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004547 { # characters
4548 $Val = chr($Val);
4549 }
4550 return $Val;
4551 }
4552 elsif($InfoType eq "string_cst") {
4553 return getNodeStrCst($InfoId);
4554 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004555 elsif($InfoType eq "var_decl")
4556 {
4557 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4558 return $Name;
4559 }
4560 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004561 }
4562 }
4563 return undef;
4564}
4565
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004566sub set_Class_And_Namespace($)
4567{
4568 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004569 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004570 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004571 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004572 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004573 my $NSInfoId = $1;
4574 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4575 {
4576 if($InfoType eq "namespace_decl") {
4577 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4578 }
4579 elsif($InfoType eq "record_type") {
4580 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4581 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004582 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004583 }
4584 }
4585 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4586 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004587 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004588 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004589 { # skip
4590 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004591 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004592 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004593
4594 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004595}
4596
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004597sub debugMangling($)
4598{
4599 my $LibVersion = $_[0];
4600 my %Mangled = ();
4601 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
4602 {
4603 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
4604 {
4605 if($Mngl=~/\A(_Z|\?)/) {
4606 $Mangled{$Mngl}=$InfoId;
4607 }
4608 }
4609 }
4610 translateSymbols(keys(%Mangled), $LibVersion);
4611 foreach my $Mngl (keys(%Mangled))
4612 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004613 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
4614 my $U2 = $tr_name{$Mngl};
4615 if($U1 ne $U2) {
4616 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004617 }
4618 }
4619}
4620
4621sub linkSymbol($)
4622{ # link symbols from shared libraries
4623 # with the symbols from header files
4624 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004625 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004626 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
4627 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004628 { # 1. GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
4629 # 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 +04004630 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004631 {
4632 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
4633 return correct_incharge($InfoId, $Version, $Mangled);
4634 }
4635 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004636 if($CheckHeadersOnly
4637 or not $BinaryOnly)
4638 { # 1. --headers-only mode
4639 # 2. not mangled src-only symbols
4640 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
4641 return $Mangled;
4642 }
4643 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004644 }
4645 return "";
4646}
4647
4648sub setLanguage($$)
4649{
4650 my ($LibVersion, $Lang) = @_;
4651 if(not $UserLang) {
4652 $COMMON_LANGUAGE{$LibVersion} = $Lang;
4653 }
4654}
4655
4656sub getSymbolInfo($)
4657{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004658 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004659 if(isInternal($InfoId)) {
4660 return;
4661 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004662 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
4663 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004664 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
4665 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004666 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004667 return;
4668 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004669 setFuncAccess($InfoId);
4670 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004671 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
4672 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004673 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004674 return;
4675 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004676
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004677 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004678 if($SymbolInfo{$Version}{$InfoId}{"Return"} = getFuncReturn($InfoId))
4679 {
4680 if(not $TypeInfo{$Version}{$SymbolInfo{$Version}{$InfoId}{"Return"}}{"Name"})
4681 { # templates
4682 delete($SymbolInfo{$Version}{$InfoId});
4683 return;
4684 }
4685 }
4686 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
4687 {
4688 if(defined $MissedTypedef{$Version}{$Rid})
4689 {
4690 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
4691 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
4692 }
4693 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004694 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004695 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
4696 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004697 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004698 my $Orig = getFuncOrig($InfoId);
4699 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004700 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
4701 {
4702 delete($SymbolInfo{$Version}{$InfoId});
4703 return;
4704 }
4705
4706 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004707 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004708 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004709 return;
4710 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004711
4712 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004713 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004714 my @TParams = getTParams($Orig, "Func");
4715 if(not @TParams)
4716 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004717 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004718 return;
4719 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004720 foreach my $Pos (0 .. $#TParams) {
4721 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"}=$TParams[$Pos];
4722 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004723 my $PrmsInLine = join(", ", @TParams);
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004724 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
4725 { # operator<< <T>, operator>> <T>
4726 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
4727 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004728 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".$PrmsInLine.">";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004729 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004730 }
4731 else
4732 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004733 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004734 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004735 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
4736 {
4737 if($OSgroup eq "windows")
4738 { # cut the offset
4739 $MnglName=~s/\@\d+\Z//g;
4740 }
4741 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
4742
4743 # NOTE: mangling of some symbols may change depending on GCC version
4744 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
4745 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
4746 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004747
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004748 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004749 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004750 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004751 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004752 return;
4753 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004754 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004755 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004756 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004757 if($Skip)
4758 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004759 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004760 return;
4761 }
4762 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004763 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
4764 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
4765 }
4766
4767 if(set_Class_And_Namespace($InfoId))
4768 {
4769 delete($SymbolInfo{$Version}{$InfoId});
4770 return;
4771 }
4772
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004773 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4774 {
4775 if(not $TypeInfo{$Version}{$ClassId}{"Name"})
4776 { # templates
4777 delete($SymbolInfo{$Version}{$InfoId});
4778 return;
4779 }
4780 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004781 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
4782 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004783 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004784 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004785 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004786 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004787 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004788 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004789 }
4790 if($COMMON_LANGUAGE{$Version} eq "C++")
4791 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004792 # C++ or --headers-only mode
4793 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004794 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004795 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
4796 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004797 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004798 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004799 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004800 if(my $Mangled = linkSymbol($InfoId)) {
4801 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004802 }
4803 }
4804 if($OStarget eq "windows")
4805 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004806 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004807 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004808 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004809 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004810 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004811 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004812 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004813 }
4814 }
4815 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004816 else
4817 { # not mangled in C
4818 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4819 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004820 if(not $CheckHeadersOnly
4821 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
4822 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
4823 {
4824 my $Incorrect = 0;
4825
4826 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
4827 {
4828 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
4829 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
4830 { # mangled in the TU dump, but not mangled in the library
4831 $Incorrect = 1;
4832 }
4833 }
4834 else
4835 {
4836 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
4837 { # all C++ functions are not mangled in the TU dump
4838 $Incorrect = 1;
4839 }
4840 }
4841 if($Incorrect)
4842 {
4843 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
4844 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4845 }
4846 }
4847 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004848 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004849 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004850 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004851 return;
4852 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004853 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04004854 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004855 { # identify virtual and pure virtual functions
4856 # NOTE: constructors cannot be virtual
4857 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
4858 # in the TU dump, so taking it from the original symbol
4859 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
4860 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
4861 { # NOTE: D2 destructors are not present in a v-table
4862 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
4863 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004864 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004865 if(isInline($InfoId)) {
4866 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004867 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004868 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04004869 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
4870 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004871 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
4872 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004873 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004874 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04004875 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004876 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004877 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004878 }
4879 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004880 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
4881 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004882 if(not $ExtraDump)
4883 {
4884 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
4885 { # non-target symbols
4886 delete($SymbolInfo{$Version}{$InfoId});
4887 return;
4888 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004889 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004890 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004891 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
4892 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
4893 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
4894 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004895 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004896 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
4897 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004898 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004899 return;
4900 }
4901 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004902 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004903 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004904 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004905 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004906 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004907 return;
4908 }
4909 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004910 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004911 }
4912 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004913 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
4914 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4915 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004916 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004917 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
4918 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004919 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004920 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004921 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004922 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004923 }
4924 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004925 if(getFuncLink($InfoId) eq "Static") {
4926 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004927 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004928 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
4929 {
4930 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
4931 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004932 if($Unmangled=~/\.\_\d/)
4933 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004934 delete($SymbolInfo{$Version}{$InfoId});
4935 return;
4936 }
4937 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004938 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004939 delete($SymbolInfo{$Version}{$InfoId}{"Type"});
4940 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
4941 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004942 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004943 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
4944 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004945 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004946
4947 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
4948 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
4949 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004950
4951 if($ExtraDump) {
4952 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
4953 }
4954}
4955
4956sub guessHeader($)
4957{
4958 my $InfoId = $_[0];
4959 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4960 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
4961 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
4962 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
4963 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
4964 {
4965 if(get_filename($HPath) eq $Header)
4966 {
4967 my $HDir = get_filename(get_dirname($HPath));
4968 if($HDir ne "include"
4969 and $HDir=~/\A[a-z]+\Z/i) {
4970 return join_P($HDir, $Header);
4971 }
4972 }
4973 }
4974 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004975}
4976
4977sub isInline($)
4978{ # "body: undefined" in the tree
4979 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004980 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4981 {
4982 if($Info=~/ undefined /i) {
4983 return 0;
4984 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004985 }
4986 return 1;
4987}
4988
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04004989sub hasThrow($)
4990{
4991 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4992 {
4993 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
4994 return getTreeAttr_Unql($1, "unql");
4995 }
4996 }
4997 return 1;
4998}
4999
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005000sub getTypeId($)
5001{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005002 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5003 {
5004 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5005 return $1;
5006 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005007 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005008 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005009}
5010
5011sub setTypeMemb($$)
5012{
5013 my ($TypeId, $TypeAttr) = @_;
5014 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005015 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005016 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005017 if($TypeType eq "Enum")
5018 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005019 my $MInfoId = getTreeAttr_Csts($TypeId);
5020 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005021 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005022 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5023 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005024 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005025 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5026 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005027 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005028 }
5029 }
5030 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5031 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005032 my $MInfoId = getTreeAttr_Flds($TypeId);
5033 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005034 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005035 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5036 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005037 if(not $IType or $IType ne "field_decl")
5038 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005039
5040 if($IType eq "var_decl")
5041 { # static field
5042 $StaticFields = 1;
5043 }
5044
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005045 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005046 next;
5047 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005048 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005049 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005050 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005051 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005052 }
5053 if(not $StructMembName)
5054 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005055 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005056 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005057 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005058 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5059 if(isAnon($UnnamedTName))
5060 { # rename unnamed fields to unnamed0, unnamed1, ...
5061 $StructMembName = "unnamed".($UnnamedPos++);
5062 }
5063 }
5064 }
5065 if(not $StructMembName)
5066 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005067 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005068 next;
5069 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005070 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005071 if(defined $MissedTypedef{$Version}{$MembTypeId})
5072 {
5073 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5074 $MembTypeId = $AddedTid;
5075 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005076 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005077 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5078 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005079 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005080 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005081 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5082 }
5083 if($MInfo=~/spec:\s*mutable /)
5084 { # mutable fields
5085 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005086 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005087 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005088 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5089 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005090 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005091 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005092 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005093 }
5094 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005095 { # in bytes
5096 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005097 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005098
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005099 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005100 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005101 }
5102 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005103
5104 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005105}
5106
5107sub setFuncParams($)
5108{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005109 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005110 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005111 if(getFuncType($InfoId) eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005112 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005113 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5114 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005115 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005116 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005117 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5118 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005119 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005120 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5121 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005122 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005123 else
5124 { # skip
5125 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005126 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005127 # skip "this"-parameter
5128 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005129 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005130 my ($Pos, $Vtt_Pos) = (0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005131 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005132 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005133 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5134 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5135 if(not $ParamName)
5136 { # unnamed
5137 $ParamName = "p".($Pos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005138 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005139 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5140 {
5141 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5142 $ParamTypeId = $AddedTid;
5143 }
5144 }
5145 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005146 if(not $PType or $PType eq "Unknown") {
5147 return 1;
5148 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005149 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005150 if(not $PTName) {
5151 return 1;
5152 }
5153 if($PTName eq "void") {
5154 last;
5155 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005156 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005157 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005158 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005159 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005160 $ParamInfoId = getNextElem($ParamInfoId);
5161 next;
5162 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005163 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5164 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005165 if(my $Algn = getAlgn($ParamInfoId)) {
5166 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5167 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005168 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"}) {
5169 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($Pos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005170 }
5171 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5172 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005173 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005174 }
5175 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005176 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005177 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005178 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005179 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005180 }
5181 return 0;
5182}
5183
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005184sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005185{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005186 my ($InfoId, $Vtt_Pos) = @_;
5187 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005188 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005189 if(getFuncType($InfoId) eq "Method") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005190 $ParamListElemId = getNextElem($ParamListElemId);
5191 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005192 if(not $ParamListElemId)
5193 { # foo(...)
5194 return 1;
5195 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005196 my $HaveVoid = 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005197 my $Pos = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005198 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005199 { # actual params: may differ from formal args
5200 # formal int*const
5201 # actual: int*
5202 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005203 {
5204 $Vtt_Pos=-1;
5205 $ParamListElemId = getNextElem($ParamListElemId);
5206 next;
5207 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005208 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5209 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005210 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005211 $HaveVoid = 1;
5212 last;
5213 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005214 elsif(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005215 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005216 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005217 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5218 { # unnamed
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005219 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($Pos+1);
5220 }
5221 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005222 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005223 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005224 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5225 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005226 if($PurpType eq "nop_expr")
5227 { # func ( const char* arg = (const char*)(void*)0 )
5228 $PurpId = getTreeAttr_Op($PurpId);
5229 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005230 my $Val = getInitVal($PurpId, $ParamTypeId);
5231 if(defined $Val) {
5232 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5233 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005234 }
5235 }
5236 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005237 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005238 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005239 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005240}
5241
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005242sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005243{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005244 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5245 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005246 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5247 return $1;
5248 }
5249 }
5250 return "";
5251}
5252
5253sub getTreeAttr_Chain($)
5254{
5255 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5256 {
5257 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5258 return $1;
5259 }
5260 }
5261 return "";
5262}
5263
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005264sub getTreeAttr_Unql($)
5265{
5266 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5267 {
5268 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5269 return $1;
5270 }
5271 }
5272 return "";
5273}
5274
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005275sub getTreeAttr_Scpe($)
5276{
5277 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5278 {
5279 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5280 return $1;
5281 }
5282 }
5283 return "";
5284}
5285
5286sub getTreeAttr_Type($)
5287{
5288 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5289 {
5290 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5291 return $1;
5292 }
5293 }
5294 return "";
5295}
5296
5297sub getTreeAttr_Name($)
5298{
5299 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5300 {
5301 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5302 return $1;
5303 }
5304 }
5305 return "";
5306}
5307
5308sub getTreeAttr_Mngl($)
5309{
5310 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5311 {
5312 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5313 return $1;
5314 }
5315 }
5316 return "";
5317}
5318
5319sub getTreeAttr_Prms($)
5320{
5321 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5322 {
5323 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5324 return $1;
5325 }
5326 }
5327 return "";
5328}
5329
5330sub getTreeAttr_Fncs($)
5331{
5332 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5333 {
5334 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5335 return $1;
5336 }
5337 }
5338 return "";
5339}
5340
5341sub getTreeAttr_Csts($)
5342{
5343 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5344 {
5345 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5346 return $1;
5347 }
5348 }
5349 return "";
5350}
5351
5352sub getTreeAttr_Purp($)
5353{
5354 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5355 {
5356 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5357 return $1;
5358 }
5359 }
5360 return "";
5361}
5362
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005363sub getTreeAttr_Op($)
5364{
5365 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5366 {
5367 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5368 return $1;
5369 }
5370 }
5371 return "";
5372}
5373
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005374sub getTreeAttr_Valu($)
5375{
5376 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5377 {
5378 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5379 return $1;
5380 }
5381 }
5382 return "";
5383}
5384
5385sub getTreeAttr_Flds($)
5386{
5387 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5388 {
5389 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5390 return $1;
5391 }
5392 }
5393 return "";
5394}
5395
5396sub getTreeAttr_Args($)
5397{
5398 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5399 {
5400 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005401 return $1;
5402 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005403 }
5404 return "";
5405}
5406
5407sub getTreeValue($)
5408{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005409 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5410 {
5411 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5412 return $1;
5413 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005414 }
5415 return "";
5416}
5417
5418sub getTreeAccess($)
5419{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005420 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005421 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005422 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5423 {
5424 my $Access = $1;
5425 if($Access eq "prot") {
5426 return "protected";
5427 }
5428 elsif($Access eq "priv") {
5429 return "private";
5430 }
5431 }
5432 elsif($Info=~/ protected /)
5433 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005434 return "protected";
5435 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005436 elsif($Info=~/ private /)
5437 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005438 return "private";
5439 }
5440 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005441 return "public";
5442}
5443
5444sub setFuncAccess($)
5445{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005446 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005447 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005448 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005449 }
5450 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005451 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005452 }
5453}
5454
5455sub setTypeAccess($$)
5456{
5457 my ($TypeId, $TypeAttr) = @_;
5458 my $Access = getTreeAccess($TypeId);
5459 if($Access eq "protected") {
5460 $TypeAttr->{"Protected"} = 1;
5461 }
5462 elsif($Access eq "private") {
5463 $TypeAttr->{"Private"} = 1;
5464 }
5465}
5466
5467sub setFuncKind($)
5468{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005469 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5470 {
5471 if($Info=~/pseudo tmpl/) {
5472 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5473 }
5474 elsif($Info=~/ constructor /) {
5475 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5476 }
5477 elsif($Info=~/ destructor /) {
5478 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5479 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005480 }
5481}
5482
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005483sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005484{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005485 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5486 {
5487 if($Info=~/spec[ ]*:[ ]*pure /) {
5488 return "PureVirt";
5489 }
5490 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5491 return "Virt";
5492 }
5493 elsif($Info=~/ pure\s+virtual /)
5494 { # support for old GCC versions
5495 return "PureVirt";
5496 }
5497 elsif($Info=~/ virtual /)
5498 { # support for old GCC versions
5499 return "Virt";
5500 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005501 }
5502 return "";
5503}
5504
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005505sub getFuncLink($)
5506{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005507 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5508 {
5509 if($Info=~/link[ ]*:[ ]*static /) {
5510 return "Static";
5511 }
5512 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005513 return $1;
5514 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005515 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005516 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005517}
5518
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005519sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005520{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005521 my ($Symbol, $LibVersion) = @_;
5522 return "" if(not $Symbol or not $LibVersion);
5523 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5524 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005525 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005526 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5527 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5528 }
5529 }
5530 if($NS)
5531 {
5532 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5533 return $NS;
5534 }
5535 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005536 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005537 while($NS=~s/::[^:]+\Z//)
5538 {
5539 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5540 return $NS;
5541 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005542 }
5543 }
5544 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005545
5546 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005547}
5548
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005549sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005550{
5551 my ($TypeName, $LibVersion) = @_;
5552 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005553 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005554 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005555 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5556 return $NS;
5557 }
5558 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005559 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005560 while($NS=~s/::[^:]+\Z//)
5561 {
5562 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5563 return $NS;
5564 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005565 }
5566 }
5567 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005568 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005569}
5570
5571sub getNameSpace($)
5572{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005573 my $InfoId = $_[0];
5574 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005575 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005576 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005577 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005578 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005579 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005580 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
5581 {
5582 my $NameSpace = getTreeStr($1);
5583 if($NameSpace eq "::")
5584 { # global namespace
5585 return "";
5586 }
5587 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
5588 $NameSpace = $BaseNameSpace."::".$NameSpace;
5589 }
5590 $NestedNameSpaces{$Version}{$NameSpace} = 1;
5591 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005592 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005593 else {
5594 return "";
5595 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005596 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005597 elsif($InfoType eq "record_type")
5598 { # inside data type
5599 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
5600 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005601 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005602 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005603 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005604 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005605}
5606
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005607sub getEnumMembVal($)
5608{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005609 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005610 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005611 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
5612 {
5613 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
5614 {
5615 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
5616 { # in newer versions of GCC the value is in the "const_decl->cnst" node
5617 return getTreeValue($1);
5618 }
5619 else
5620 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
5621 return getTreeValue($1);
5622 }
5623 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005624 }
5625 }
5626 return "";
5627}
5628
5629sub getSize($)
5630{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005631 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5632 {
5633 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
5634 return getTreeValue($1);
5635 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005636 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005637 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005638}
5639
5640sub getAlgn($)
5641{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005642 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5643 {
5644 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
5645 return $1;
5646 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005647 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005648 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005649}
5650
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005651sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005652{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005653 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5654 {
5655 if($Info=~/ bitfield /) {
5656 return getSize($_[0]);
5657 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005658 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005659 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005660}
5661
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005662sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005663{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005664 if(my $Chan = getTreeAttr_Chan($_[0])) {
5665 return $Chan;
5666 }
5667 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
5668 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005669 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005670 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005671}
5672
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005673sub registerHeader($$)
5674{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005675 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005676 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005677 return "";
5678 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005679 if(is_abs($Header) and not -f $Header)
5680 { # incorrect absolute path
5681 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005682 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005683 if(skipHeader($Header, $LibVersion))
5684 { # skip
5685 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005686 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005687 if(my $Header_Path = identifyHeader($Header, $LibVersion))
5688 {
5689 detect_header_includes($Header_Path, $LibVersion);
5690
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005691 if(defined $Tolerance and $Tolerance=~/3/)
5692 { # 3 - skip headers that include non-Linux headers
5693 if($OSgroup ne "windows")
5694 {
5695 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
5696 {
5697 if(specificHeader($Inc, "windows")) {
5698 return "";
5699 }
5700 }
5701 }
5702 }
5703
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005704 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
5705 { # redirect
5706 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
5707 or skipHeader($RHeader_Path, $LibVersion))
5708 { # skip
5709 return "";
5710 }
5711 $Header_Path = $RHeader_Path;
5712 }
5713 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
5714 { # skip
5715 return "";
5716 }
5717
5718 if(my $HName = get_filename($Header_Path))
5719 { # register
5720 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
5721 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
5722 }
5723
5724 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
5725 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005726 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005727 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005728 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005729 }
5730
5731 if($CheckHeadersOnly
5732 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
5733 { # /usr/include/c++/4.6.1/...
5734 $STDCXX_TESTING = 1;
5735 }
5736
5737 return $Header_Path;
5738 }
5739 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005740}
5741
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005742sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005743{
5744 my ($Dir, $WithDeps, $LibVersion) = @_;
5745 $Dir=~s/[\/\\]+\Z//g;
5746 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005747 $Dir = get_abs_path($Dir);
5748 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005749 if($WithDeps)
5750 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005751 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
5752 return;
5753 }
5754 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
5755 $Mode = "DepsOnly";
5756 }
5757 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005758 else
5759 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005760 if($RegisteredDirs{$LibVersion}{$Dir}{1}
5761 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
5762 return;
5763 }
5764 }
5765 $Header_Dependency{$LibVersion}{$Dir} = 1;
5766 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
5767 if($Mode eq "DepsOnly")
5768 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005769 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005770 $Header_Dependency{$LibVersion}{$Path} = 1;
5771 }
5772 return;
5773 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005774 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005775 {
5776 if($WithDeps)
5777 {
5778 my $SubDir = $Path;
5779 while(($SubDir = get_dirname($SubDir)) ne $Dir)
5780 { # register all sub directories
5781 $Header_Dependency{$LibVersion}{$SubDir} = 1;
5782 }
5783 }
5784 next if(is_not_header($Path));
5785 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005786 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005787 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005788 $Include_Neighbors{$LibVersion}{$Part} = $Path;
5789 }
5790 }
5791 if(get_filename($Dir) eq "include")
5792 { # search for "lib/include/" directory
5793 my $LibDir = $Dir;
5794 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005795 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005796 }
5797 }
5798}
5799
5800sub parse_redirect($$$)
5801{
5802 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005803 my @Errors = ();
5804 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
5805 push(@Errors, $1);
5806 }
5807 my $Redirect = "";
5808 foreach (@Errors)
5809 {
5810 s/\s{2,}/ /g;
5811 if(/(only|must\ include
5812 |update\ to\ include
5813 |replaced\ with
5814 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005815 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005816 {
5817 $Redirect = $2;
5818 last;
5819 }
5820 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
5821 {
5822 $Redirect = $2;
5823 last;
5824 }
5825 elsif(/this\ header\ should\ not\ be\ used
5826 |programs\ should\ not\ directly\ include
5827 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
5828 |is\ not\ supported\ API\ for\ general\ use
5829 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005830 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005831 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
5832 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
5833 }
5834 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005835 if($Redirect)
5836 {
5837 $Redirect=~s/\A<//g;
5838 $Redirect=~s/>\Z//g;
5839 }
5840 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005841}
5842
5843sub parse_includes($$)
5844{
5845 my ($Content, $Path) = @_;
5846 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005847 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005848 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005849 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005850 my $Method = substr($Header, 0, 1, "");
5851 substr($Header, length($Header)-1, 1, "");
5852 $Header = path_format($Header, $OSgroup);
5853 if($Method eq "\"" or is_abs($Header))
5854 {
5855 if(-e join_P(get_dirname($Path), $Header))
5856 { # relative path exists
5857 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005858 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005859 else
5860 { # include "..." that doesn't exist is equal to include <...>
5861 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005862 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005863 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005864 else {
5865 $Includes{$Header} = 1;
5866 }
5867 }
5868 if($ExtraInfo)
5869 {
5870 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
5871 { # FT_FREETYPE_H
5872 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005873 }
5874 }
5875 return \%Includes;
5876}
5877
5878sub ignore_path($)
5879{
5880 my $Path = $_[0];
5881 if($Path=~/\~\Z/)
5882 {# skipping system backup files
5883 return 1;
5884 }
5885 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
5886 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
5887 return 1;
5888 }
5889 return 0;
5890}
5891
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005892sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005893{
5894 my ($ArrRef, $W) = @_;
5895 return if(length($W)<2);
5896 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
5897}
5898
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005899sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005900{
5901 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005902
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005903 $H1=~s/\.[a-z]+\Z//ig;
5904 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005905
5906 my $Hname1 = get_filename($H1);
5907 my $Hname2 = get_filename($H2);
5908 my $HDir1 = get_dirname($H1);
5909 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005910 my $Dirname1 = get_filename($HDir1);
5911 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005912
5913 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
5914 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
5915
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005916 if($_[0] eq $_[1]
5917 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005918 return 0;
5919 }
5920 elsif($H1=~/\A\Q$H2\E/) {
5921 return 1;
5922 }
5923 elsif($H2=~/\A\Q$H1\E/) {
5924 return -1;
5925 }
5926 elsif($HDir1=~/\Q$Hname1\E/i
5927 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005928 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005929 return -1;
5930 }
5931 elsif($HDir2=~/\Q$Hname2\E/i
5932 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005933 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005934 return 1;
5935 }
5936 elsif($Hname1=~/\Q$Dirname1\E/i
5937 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005938 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005939 return -1;
5940 }
5941 elsif($Hname2=~/\Q$Dirname2\E/i
5942 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005943 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005944 return 1;
5945 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005946 elsif($Hname1=~/(config|lib|util)/i
5947 and $Hname2!~/(config|lib|util)/i)
5948 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005949 return -1;
5950 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005951 elsif($Hname2=~/(config|lib|util)/i
5952 and $Hname1!~/(config|lib|util)/i)
5953 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005954 return 1;
5955 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005956 else
5957 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005958 my $R1 = checkRelevance($H1);
5959 my $R2 = checkRelevance($H2);
5960 if($R1 and not $R2)
5961 { # libebook/e-book.h
5962 return -1;
5963 }
5964 elsif($R2 and not $R1)
5965 { # libebook/e-book.h
5966 return 1;
5967 }
5968 else
5969 {
5970 return (lc($H1) cmp lc($H2));
5971 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005972 }
5973}
5974
5975sub searchForHeaders($)
5976{
5977 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005978
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005979 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005980 registerGccHeaders();
5981
5982 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
5983 { # c++ standard include paths
5984 registerCppHeaders();
5985 }
5986
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005987 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005988 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
5989 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005990 {
5991 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005992 if($SystemRoot)
5993 {
5994 if(is_abs($Path)) {
5995 $Path = $SystemRoot.$Path;
5996 }
5997 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005998 if(not -e $Path) {
5999 exitStatus("Access_Error", "can't access \'$Path\'");
6000 }
6001 elsif(-f $Path) {
6002 exitStatus("Access_Error", "\'$Path\' - not a directory");
6003 }
6004 elsif(-d $Path)
6005 {
6006 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006007 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006008 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6009 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006010 }
6011 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006012 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006013 }
6014 }
6015 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006016 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006017 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6018 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006019
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006020 # registering directories
6021 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6022 {
6023 next if(not -e $Path);
6024 $Path = get_abs_path($Path);
6025 $Path = path_format($Path, $OSgroup);
6026 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006027 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006028 }
6029 elsif(-f $Path)
6030 {
6031 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006032 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006033 and not $LocalIncludes{$Dir})
6034 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006035 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006036 # if(my $OutDir = get_dirname($Dir))
6037 # { # registering the outer directory
6038 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6039 # and not $LocalIncludes{$OutDir}) {
6040 # registerDir($OutDir, 0, $LibVersion);
6041 # }
6042 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006043 }
6044 }
6045 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006046
6047 # clean memory
6048 %RegisteredDirs = ();
6049
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006050 # registering headers
6051 my $Position = 0;
6052 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6053 {
6054 if(is_abs($Dest) and not -e $Dest) {
6055 exitStatus("Access_Error", "can't access \'$Dest\'");
6056 }
6057 $Dest = path_format($Dest, $OSgroup);
6058 if(is_header($Dest, 1, $LibVersion))
6059 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006060 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006061 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6062 }
6063 }
6064 elsif(-d $Dest)
6065 {
6066 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006067 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006068 {
6069 next if(ignore_path($Path));
6070 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006071 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006072 push(@Registered, $HPath);
6073 }
6074 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006075 @Registered = sort {sortHeaders($a, $b)} @Registered;
6076 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006077 foreach my $Path (@Registered) {
6078 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6079 }
6080 }
6081 else {
6082 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6083 }
6084 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006085
6086 if(defined $Tolerance and $Tolerance=~/4/)
6087 { # 4 - skip headers included by others
6088 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6089 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006090 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006091 delete($Registered_Headers{$LibVersion}{$Path});
6092 }
6093 }
6094 }
6095
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006096 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6097 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006098 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006099 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006100 if(is_abs($Header) and not -f $Header) {
6101 exitStatus("Access_Error", "can't access file \'$Header\'");
6102 }
6103 $Header = path_format($Header, $OSgroup);
6104 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6105 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006106 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006107 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006108 }
6109 else {
6110 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6111 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006112 }
6113 }
6114 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6115 { # set relative paths (for duplicates)
6116 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6117 { # search for duplicates
6118 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6119 my $Prefix = get_dirname($FirstPath);
6120 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6121 { # detect a shortest distinguishing prefix
6122 my $NewPrefix = $1;
6123 my %Identity = ();
6124 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6125 {
6126 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6127 $Identity{$Path} = $1;
6128 }
6129 }
6130 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6131 { # all names are differend with current prefix
6132 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6133 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6134 }
6135 last;
6136 }
6137 $Prefix = $NewPrefix; # increase prefix
6138 }
6139 }
6140 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006141
6142 # clean memory
6143 %HeaderName_Paths = ();
6144
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006145 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6146 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006147 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006148 my ($Pos, $PairPos) = (-1, -1);
6149 my ($Path, $PairPath) = ();
6150 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6151 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6152 foreach my $Header_Path (@Paths)
6153 {
6154 if(get_filename($Header_Path) eq $PairName)
6155 {
6156 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6157 $PairPath = $Header_Path;
6158 }
6159 if(get_filename($Header_Path) eq $HeaderName)
6160 {
6161 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6162 $Path = $Header_Path;
6163 }
6164 }
6165 if($PairPos!=-1 and $Pos!=-1
6166 and int($PairPos)<int($Pos))
6167 {
6168 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6169 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6170 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6171 }
6172 }
6173 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6174 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6175 }
6176}
6177
6178sub detect_real_includes($$)
6179{
6180 my ($AbsPath, $LibVersion) = @_;
6181 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6182 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6183 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6184 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6185 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006186 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6187
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006188 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6189 return () if(not $Path);
6190 open(PREPROC, $Path);
6191 while(<PREPROC>)
6192 {
6193 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6194 {
6195 my $Include = path_format($1, $OSgroup);
6196 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6197 next;
6198 }
6199 if($Include eq $AbsPath) {
6200 next;
6201 }
6202 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6203 }
6204 }
6205 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006206 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6207}
6208
6209sub detect_header_includes($$)
6210{
6211 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006212 return if(not $LibVersion or not $Path);
6213 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6214 return;
6215 }
6216 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6217
6218 if(not -e $Path) {
6219 return;
6220 }
6221
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006222 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006223 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6224 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006225 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006226 {
6227 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006228 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006229 }
6230 if($RedirectPath ne $Path) {
6231 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6232 }
6233 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006234 else
6235 { # can't find
6236 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6237 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006238 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006239 if(my $Inc = parse_includes($Content, $Path))
6240 {
6241 foreach my $Include (keys(%{$Inc}))
6242 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006243 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006244
6245 if(defined $Tolerance and $Tolerance=~/4/)
6246 {
6247 if(my $HPath = identifyHeader($Include, $LibVersion))
6248 {
6249 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6250 }
6251 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006253 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006254}
6255
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006256sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006257{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006258 my $Path = $_[0];
6259 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006260 if($OStarget eq "symbian")
6261 {
6262 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6263 { # epoc32/include/libc/{stdio, ...}.h
6264 return 1;
6265 }
6266 }
6267 else
6268 {
6269 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6270 { # /usr/include/{stdio, ...}.h
6271 return 1;
6272 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006273 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006274 return 0;
6275}
6276
6277sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006278{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006279 my $Dir = $_[0];
6280 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006281 if($OStarget eq "symbian")
6282 {
6283 if(get_filename($OutDir) eq "libc"
6284 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6285 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6286 return 1;
6287 }
6288 }
6289 else
6290 { # linux
6291 if($OutDir eq "/usr/include"
6292 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6293 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6294 return 1;
6295 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006296 }
6297 return 0;
6298}
6299
6300sub detect_recursive_includes($$)
6301{
6302 my ($AbsPath, $LibVersion) = @_;
6303 return () if(not $AbsPath);
6304 if(isCyclical(\@RecurInclude, $AbsPath)) {
6305 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6306 }
6307 my ($AbsDir, $Name) = separate_path($AbsPath);
6308 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006309 { # system GLIBC internals
6310 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006311 }
6312 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6313 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6314 }
6315 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006316
6317 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6318 { # skip /usr/include/c++/*/ headers
6319 return () if(not $ExtraInfo);
6320 }
6321
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006322 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006323 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006324 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006325 { # check "real" (non-"model") include paths
6326 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6327 pop(@RecurInclude);
6328 return @Paths;
6329 }
6330 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6331 detect_header_includes($AbsPath, $LibVersion);
6332 }
6333 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6334 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006335 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006336 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006337 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006338 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006339 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006340 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006341 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006342 }
6343 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006344 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006345 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006346 { # search for the nearest header
6347 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006348 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006349 if(-f $Candidate) {
6350 $HPath = $Candidate;
6351 }
6352 }
6353 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006354 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006355 }
6356 next if(not $HPath);
6357 if($HPath eq $AbsPath) {
6358 next;
6359 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006360
6361 if($Debug)
6362 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006363# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6364# {
6365# print STDERR "$AbsPath -> $HPath\n";
6366# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006367 }
6368
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006369 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6370 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006371 { # only include <...>, skip include "..." prefixes
6372 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6373 }
6374 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6375 {
6376 if($IncPath eq $AbsPath) {
6377 next;
6378 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006379 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6380 if($RIncType==-1)
6381 { # include "..."
6382 $RIncType = $IncType;
6383 }
6384 elsif($RIncType==2)
6385 {
6386 if($IncType!=-1) {
6387 $RIncType = $IncType;
6388 }
6389 }
6390 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006391 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6392 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6393 }
6394 }
6395 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6396 {
6397 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6398 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6399 { # distinguish math.h from glibc and math.h from the tested library
6400 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6401 last;
6402 }
6403 }
6404 }
6405 pop(@RecurInclude);
6406 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6407}
6408
6409sub find_in_framework($$$)
6410{
6411 my ($Header, $Framework, $LibVersion) = @_;
6412 return "" if(not $Header or not $Framework or not $LibVersion);
6413 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6414 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6415 }
6416 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6417 {
6418 if(get_filename($Dependency) eq $Framework
6419 and -f get_dirname($Dependency)."/".$Header) {
6420 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6421 }
6422 }
6423 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6424}
6425
6426sub find_in_defaults($)
6427{
6428 my $Header = $_[0];
6429 return "" if(not $Header);
6430 if(defined $Cache{"find_in_defaults"}{$Header}) {
6431 return $Cache{"find_in_defaults"}{$Header};
6432 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006433 foreach my $Dir (@DefaultIncPaths,
6434 @DefaultGccPaths,
6435 @DefaultCppPaths,
6436 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006437 {
6438 next if(not $Dir);
6439 if(-f $Dir."/".$Header) {
6440 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6441 }
6442 }
6443 return ($Cache{"find_in_defaults"}{$Header}="");
6444}
6445
6446sub cmp_paths($$)
6447{
6448 my ($Path1, $Path2) = @_;
6449 my @Parts1 = split(/[\/\\]/, $Path1);
6450 my @Parts2 = split(/[\/\\]/, $Path2);
6451 foreach my $Num (0 .. $#Parts1)
6452 {
6453 my $Part1 = $Parts1[$Num];
6454 my $Part2 = $Parts2[$Num];
6455 if($GlibcDir{$Part1}
6456 and not $GlibcDir{$Part2}) {
6457 return 1;
6458 }
6459 elsif($GlibcDir{$Part2}
6460 and not $GlibcDir{$Part1}) {
6461 return -1;
6462 }
6463 elsif($Part1=~/glib/
6464 and $Part2!~/glib/) {
6465 return 1;
6466 }
6467 elsif($Part1!~/glib/
6468 and $Part2=~/glib/) {
6469 return -1;
6470 }
6471 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6472 return $CmpRes;
6473 }
6474 }
6475 return 0;
6476}
6477
6478sub checkRelevance($)
6479{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006480 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006481 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006482
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006483 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006484 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006485 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006486
6487 my $Name = lc(get_filename($Path));
6488 my $Dir = lc(get_dirname($Path));
6489
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006490 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006491
6492 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006493 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006494 my $Len = length($Token);
6495 next if($Len<=1);
6496 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6497 { # include/evolution-data-server-1.4/libebook/e-book.h
6498 return 1;
6499 }
6500 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006501 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006502 return 1;
6503 }
6504 }
6505 return 0;
6506}
6507
6508sub checkFamily(@)
6509{
6510 my @Paths = @_;
6511 return 1 if($#Paths<=0);
6512 my %Prefix = ();
6513 foreach my $Path (@Paths)
6514 {
6515 if($SystemRoot) {
6516 $Path = cut_path_prefix($Path, $SystemRoot);
6517 }
6518 if(my $Dir = get_dirname($Path))
6519 {
6520 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6521 $Prefix{$Dir} += 1;
6522 $Prefix{get_dirname($Dir)} += 1;
6523 }
6524 }
6525 foreach (sort keys(%Prefix))
6526 {
6527 if(get_depth($_)>=3
6528 and $Prefix{$_}==$#Paths+1) {
6529 return 1;
6530 }
6531 }
6532 return 0;
6533}
6534
6535sub isAcceptable($$$)
6536{
6537 my ($Header, $Candidate, $LibVersion) = @_;
6538 my $HName = get_filename($Header);
6539 if(get_dirname($Header))
6540 { # with prefix
6541 return 1;
6542 }
6543 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6544 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6545 return 1;
6546 }
6547 if(checkRelevance($Candidate))
6548 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6549 return 1;
6550 }
6551 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6552 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6553 # /usr/include/qt4/Qt/qsslconfiguration.h
6554 return 1;
6555 }
6556 if($OStarget eq "symbian")
6557 {
6558 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6559 return 1;
6560 }
6561 }
6562 return 0;
6563}
6564
6565sub isRelevant($$$)
6566{ # disallow to search for "abstract" headers in too deep directories
6567 my ($Header, $Candidate, $LibVersion) = @_;
6568 my $HName = get_filename($Header);
6569 if($OStarget eq "symbian")
6570 {
6571 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
6572 return 0;
6573 }
6574 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006575 if($OStarget ne "bsd")
6576 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006577 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
6578 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
6579 return 0;
6580 }
6581 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006582 if($OStarget ne "windows")
6583 {
6584 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
6585 { # skip /usr/include/wine/msvcrt
6586 return 0;
6587 }
6588 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006589 if(not get_dirname($Header)
6590 and $Candidate=~/[\/\\]wx[\/\\]/)
6591 { # do NOT search in system /wx/ directory
6592 # for headers without a prefix: sstream.h
6593 return 0;
6594 }
6595 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
6596 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
6597 { # skip ../c++/3.3.3/ if using ../c++/4.5/
6598 return 0;
6599 }
6600 if($Candidate=~/[\/\\]asm-/
6601 and (my $Arch = getArch($LibVersion)) ne "unknown")
6602 { # arch-specific header files
6603 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
6604 {# skip ../asm-arm/ if using x86 architecture
6605 return 0;
6606 }
6607 }
6608 my @Candidates = getSystemHeaders($HName, $LibVersion);
6609 if($#Candidates==1)
6610 { # unique header
6611 return 1;
6612 }
6613 my @SCandidates = getSystemHeaders($Header, $LibVersion);
6614 if($#SCandidates==1)
6615 { # unique name
6616 return 1;
6617 }
6618 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
6619 if(get_depth($Candidate)-$SystemDepth>=5)
6620 { # abstract headers in too deep directories
6621 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
6622 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
6623 return 0;
6624 }
6625 }
6626 if($Header eq "parser.h"
6627 and $Candidate!~/\/libxml2\//)
6628 { # select parser.h from xml2 library
6629 return 0;
6630 }
6631 if(not get_dirname($Header)
6632 and keys(%{$SystemHeaders{$HName}})>=3)
6633 { # many headers with the same name
6634 # like thread.h included without a prefix
6635 if(not checkFamily(@Candidates)) {
6636 return 0;
6637 }
6638 }
6639 return 1;
6640}
6641
6642sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006643{ # cache function
6644 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
6645 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
6646 }
6647 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
6648}
6649
6650sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006651{
6652 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006653 if(-f $Header) {
6654 return $Header;
6655 }
6656 if(is_abs($Header) and not -f $Header)
6657 { # incorrect absolute path
6658 return "";
6659 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006660 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006661 { # too abstract configuration headers
6662 return "";
6663 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006664 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006665 if($OSgroup ne "windows")
6666 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006667 if(defined $WinHeaders{lc($HName)}
6668 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006669 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006670 return "";
6671 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006672 }
6673 if($OSgroup ne "macos")
6674 {
6675 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006676 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006677 return "";
6678 }
6679 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006680
6681 if(defined $ObsoleteHeaders{$HName})
6682 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006683 return "";
6684 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006685 if($OSgroup eq "linux" or $OSgroup eq "bsd")
6686 {
6687 if(defined $AlienHeaders{$HName}
6688 or defined $AlienHeaders{$Header})
6689 { # alien headers from other systems
6690 return "";
6691 }
6692 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006693
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006694 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006695 { # search in default paths
6696 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006697 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006698 }
6699 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006700 if(not keys(%SystemHeaders))
6701 { # register all headers in system include dirs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006702 detectSystemHeaders();
6703 }
6704 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
6705 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
6706 {
6707 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006708 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006709 }
6710 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006711 # error
6712 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006713}
6714
6715sub getSystemHeaders($$)
6716{
6717 my ($Header, $LibVersion) = @_;
6718 my @Candidates = ();
6719 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
6720 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006721 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006722 next;
6723 }
6724 push(@Candidates, $Candidate);
6725 }
6726 return @Candidates;
6727}
6728
6729sub cut_path_prefix($$)
6730{
6731 my ($Path, $Prefix) = @_;
6732 return $Path if(not $Prefix);
6733 $Prefix=~s/[\/\\]+\Z//;
6734 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
6735 return $Path;
6736}
6737
6738sub is_default_include_dir($)
6739{
6740 my $Dir = $_[0];
6741 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006742 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006743}
6744
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006745sub identifyHeader($$)
6746{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006747 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006748 if(not $Header) {
6749 return "";
6750 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006751 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006752 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
6753 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006754 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006755 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006756}
6757
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006758sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006759{ # search for header by absolute path, relative path or name
6760 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006761 if(-f $Header)
6762 { # it's relative or absolute path
6763 return get_abs_path($Header);
6764 }
6765 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
6766 and my $HeaderDir = find_in_defaults($Header))
6767 { # search for libc headers in the /usr/include
6768 # for non-libc target library before searching
6769 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006770 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006771 }
6772 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
6773 { # search in the target library paths
6774 return $Path;
6775 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006776 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006777 { # search in the internal GCC include paths
6778 return $DefaultGccHeader{$Header};
6779 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006780 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006781 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006782 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006783 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006784 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006785 { # search in the default G++ include paths
6786 return $DefaultCppHeader{$Header};
6787 }
6788 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
6789 { # search everywhere in the system
6790 return $AnyPath;
6791 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006792 elsif($OSgroup eq "macos")
6793 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
6794 if(my $Dir = get_dirname($Header))
6795 {
6796 my $RelPath = "Headers\/".get_filename($Header);
6797 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006798 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006799 }
6800 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006801 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006802 # cannot find anything
6803 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006804}
6805
6806sub getLocation($)
6807{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006808 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6809 {
6810 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006811 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006812 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006813 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006814 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006815}
6816
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006817sub getNameByInfo($)
6818{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006819 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006820 {
6821 if($Info=~/name[ ]*:[ ]*@(\d+) /)
6822 {
6823 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
6824 {
6825 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
6826 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006827 my $Str = $1;
6828 if($CppMode{$Version}
6829 and $Str=~/\Ac99_(.+)\Z/)
6830 {
6831 if($CppKeywords_A{$1}) {
6832 $Str=$1;
6833 }
6834 }
6835 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006836 }
6837 }
6838 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006839 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006840 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006841}
6842
6843sub getTreeStr($)
6844{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006845 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006846 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006847 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
6848 {
6849 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04006850 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006851 and $Str=~/\Ac99_(.+)\Z/)
6852 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006853 if($CppKeywords_A{$1}) {
6854 $Str=$1;
6855 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006856 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006857 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006858 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006859 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006860 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006861}
6862
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006863sub getFuncShortName($)
6864{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006865 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006866 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006867 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006868 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006869 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006870 {
6871 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
6872 {
6873 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
6874 return "operator ".$RName;
6875 }
6876 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006877 }
6878 else
6879 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006880 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
6881 {
6882 if(my $Ind = $Operator_Indication{$1}) {
6883 return "operator".$Ind;
6884 }
6885 elsif(not $UnknownOperator{$1})
6886 {
6887 printMsg("WARNING", "unknown operator $1");
6888 $UnknownOperator{$1} = 1;
6889 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006890 }
6891 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006892 }
6893 else
6894 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006895 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
6896 return getTreeStr($1);
6897 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006898 }
6899 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006900 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006901}
6902
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006903sub getFuncReturn($)
6904{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006905 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6906 {
6907 if($Info=~/type[ ]*:[ ]*@(\d+) /)
6908 {
6909 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
6910 return $1;
6911 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006912 }
6913 }
6914 return "";
6915}
6916
6917sub getFuncOrig($)
6918{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006919 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6920 {
6921 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
6922 return $1;
6923 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006924 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006925 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006926}
6927
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006928sub unmangleArray(@)
6929{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006930 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006931 { # MSVC mangling
6932 my $UndNameCmd = get_CmdPath("undname");
6933 if(not $UndNameCmd) {
6934 exitStatus("Not_Found", "can't find \"undname\"");
6935 }
6936 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006937 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006938 }
6939 else
6940 { # GCC mangling
6941 my $CppFiltCmd = get_CmdPath("c++filt");
6942 if(not $CppFiltCmd) {
6943 exitStatus("Not_Found", "can't find c++filt in PATH");
6944 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006945 if(not defined $CPPFILT_SUPPORT_FILE)
6946 {
6947 my $Info = `$CppFiltCmd -h 2>&1`;
6948 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
6949 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006950 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006951 if($CPPFILT_SUPPORT_FILE)
6952 { # new versions of c++filt can take a file
6953 if($#_>$MAX_CPPFILT_FILE_SIZE)
6954 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
6955 # this is fixed in the oncoming version of Binutils
6956 my @Half = splice(@_, 0, ($#_+1)/2);
6957 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006958 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006959 else
6960 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006961 writeFile("$TMP_DIR/unmangle", join("\n", @_));
6962 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
6963 if($?==139)
6964 { # segmentation fault
6965 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
6966 }
6967 return split(/\n/, $Res);
6968 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006969 }
6970 else
6971 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006972 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
6973 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006974 my @Half = splice(@_, 0, ($#_+1)/2);
6975 return (unmangleArray(@Half), unmangleArray(@_))
6976 }
6977 else
6978 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006979 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006980 my $Res = `$CppFiltCmd $NoStrip $Strings`;
6981 if($?==139)
6982 { # segmentation fault
6983 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
6984 }
6985 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006986 }
6987 }
6988 }
6989}
6990
6991sub get_SignatureNoInfo($$)
6992{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006993 my ($Symbol, $LibVersion) = @_;
6994 if($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol}) {
6995 return $Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006996 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006997 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006998 my $Signature = $tr_name{$MnglName}?$tr_name{$MnglName}:$MnglName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006999 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007000 { # C++
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04007001 # some standard typedefs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007002 $Signature=~s/\Qstd::basic_string<char, std::char_traits<char>, std::allocator<char> >\E/std::string/g;
7003 $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;
7004 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007005 if(not $CheckObjectsOnly or $OSgroup=~/linux|bsd|beos/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007006 { # ELF format marks data as OBJECT
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007007 if($GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007008 $Signature .= " [data]";
7009 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007010 elsif($Symbol!~/\A(_Z|\?)/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007011 $Signature .= " (...)";
7012 }
7013 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007014 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007015 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04007016 my $ShortName = substr($Signature, 0, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007017 $Signature=~s/\A\Q$ShortName\E/$ShortName $ChargeLevel/g;
7018 }
7019 if($SymbolVersion) {
7020 $Signature .= $VersionSpec.$SymbolVersion;
7021 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007022 return ($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007023}
7024
7025sub get_ChargeLevel($$)
7026{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007027 my ($Symbol, $LibVersion) = @_;
7028 return "" if($Symbol!~/\A(_Z|\?)/);
7029 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7030 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007031 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007032 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007033 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007034 if($Symbol=~/C1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007035 return "[in-charge]";
7036 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007037 elsif($Symbol=~/C2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007038 return "[not-in-charge]";
7039 }
7040 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007041 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007042 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007043 if($Symbol=~/D1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007044 return "[in-charge]";
7045 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007046 elsif($Symbol=~/D2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007047 return "[not-in-charge]";
7048 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007049 elsif($Symbol=~/D0E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007050 return "[in-charge-deleting]";
7051 }
7052 }
7053 }
7054 else
7055 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007056 if($Symbol=~/C1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007057 return "[in-charge]";
7058 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007059 elsif($Symbol=~/C2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007060 return "[not-in-charge]";
7061 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007062 elsif($Symbol=~/D1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007063 return "[in-charge]";
7064 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007065 elsif($Symbol=~/D2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007066 return "[not-in-charge]";
7067 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007068 elsif($Symbol=~/D0E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007069 return "[in-charge-deleting]";
7070 }
7071 }
7072 return "";
7073}
7074
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007075sub get_Signature_M($$)
7076{
7077 my ($Symbol, $LibVersion) = @_;
7078 my $Signature_M = $tr_name{$Symbol};
7079 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7080 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007081 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007082 }
7083 return $Signature_M;
7084}
7085
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007086sub get_Signature($$)
7087{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007088 my ($Symbol, $LibVersion) = @_;
7089 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7090 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007091 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007092 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
7093 if(isPrivateData($MnglName) or not $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007094 { # non-public global data
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007095 return get_SignatureNoInfo($Symbol, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007096 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007097 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007098 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7099 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007100 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007101 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7102 {
7103 $Signature .= $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::";
7104 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7105 $Signature .= "~";
7106 }
7107 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007108 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007109 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007110 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007111 }
7112 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007113 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007114 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007115 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7116 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007117 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007118 else
7119 {
7120 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007121 }
7122 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007123 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007124 {
7125 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007126 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007127 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007128 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007129 if(not $ParamTypeName) {
7130 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7131 }
7132 foreach my $Typedef (keys(%ChangedTypedef))
7133 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007134 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7135 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7136 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007137 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007138 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007139 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
7140 }
7141 else {
7142 push(@ParamArray, $ParamTypeName);
7143 }
7144 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007145 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7146 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007147 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007148 }
7149 else
7150 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007151 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007152 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007153 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007154 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007155 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007156 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7157 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007158 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007159 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007160 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7161 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007162 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007163 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007164 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7165 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007166 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007167 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007168 }
7169 }
7170 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007171 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007172 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007173 }
7174 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007175 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007176 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007177 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007178}
7179
7180sub create_member_decl($$)
7181{
7182 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007183 if($TName=~/\([\*]+\)/)
7184 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007185 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7186 return $TName;
7187 }
7188 else
7189 {
7190 my @ArraySizes = ();
7191 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7192 push(@ArraySizes, $1);
7193 }
7194 return $TName." ".$Member.join("", @ArraySizes);
7195 }
7196}
7197
7198sub getFuncType($)
7199{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007200 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7201 {
7202 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7203 {
7204 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7205 {
7206 if($Type eq "method_type") {
7207 return "Method";
7208 }
7209 elsif($Type eq "function_type") {
7210 return "Function";
7211 }
7212 else {
7213 return "Other";
7214 }
7215 }
7216 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007217 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007218 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007219}
7220
7221sub getFuncTypeId($)
7222{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007223 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7224 {
7225 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7226 return $1;
7227 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007228 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007229 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007230}
7231
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007232sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007233{ # "._N" or "$_N" in older GCC versions
7234 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007235}
7236
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007237sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007238{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007239 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7240 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007241 }
7242
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007243 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007244
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007245 if($_[1] ne "S")
7246 {
7247 $N=~s/\A[ ]+//g;
7248 $N=~s/[ ]+\Z//g;
7249 $N=~s/[ ]{2,}/ /g;
7250 }
7251
7252 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007253
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007254 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007255
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007256 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7257 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007258
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007259 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007260
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007261 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007262
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007263 if($_[1] eq "S")
7264 {
7265 if(index($N, "operator")!=-1) {
7266 $N=~s/\b(operator[ ]*)> >/$1>>/;
7267 }
7268 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007269
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007270 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007271}
7272
7273sub get_HeaderDeps($$)
7274{
7275 my ($AbsPath, $LibVersion) = @_;
7276 return () if(not $AbsPath or not $LibVersion);
7277 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7278 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7279 }
7280 my %IncDir = ();
7281 detect_recursive_includes($AbsPath, $LibVersion);
7282 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7283 {
7284 next if(not $HeaderPath);
7285 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7286 my $Dir = get_dirname($HeaderPath);
7287 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7288 {
7289 my $Dep = $Dir;
7290 if($Prefix)
7291 {
7292 if($OSgroup eq "windows")
7293 { # case insensitive seach on windows
7294 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7295 next;
7296 }
7297 }
7298 elsif($OSgroup eq "macos")
7299 { # seach in frameworks
7300 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7301 {
7302 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7303 {# frameworks
7304 my ($HFramework, $HName) = ($1, $2);
7305 $Dep = $HFramework;
7306 }
7307 else
7308 {# mismatch
7309 next;
7310 }
7311 }
7312 }
7313 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7314 { # Linux, FreeBSD
7315 next;
7316 }
7317 }
7318 if(not $Dep)
7319 { # nothing to include
7320 next;
7321 }
7322 if(is_default_include_dir($Dep))
7323 { # included by the compiler
7324 next;
7325 }
7326 if(get_depth($Dep)==1)
7327 { # too short
7328 next;
7329 }
7330 if(isLibcDir($Dep))
7331 { # do NOT include /usr/include/{sys,bits}
7332 next;
7333 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007334 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007335 }
7336 }
7337 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7338 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7339}
7340
7341sub sortIncPaths($$)
7342{
7343 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007344 if(not $ArrRef or $#{$ArrRef}<0) {
7345 return $ArrRef;
7346 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007347 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7348 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007349 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007350 return $ArrRef;
7351}
7352
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007353sub sortDeps($$$)
7354{
7355 if($Header_Dependency{$_[2]}{$_[0]}
7356 and not $Header_Dependency{$_[2]}{$_[1]}) {
7357 return 1;
7358 }
7359 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7360 and $Header_Dependency{$_[2]}{$_[1]}) {
7361 return -1;
7362 }
7363 return 0;
7364}
7365
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007366sub join_P($$)
7367{
7368 my $S = "/";
7369 if($OSgroup eq "windows") {
7370 $S = "\\";
7371 }
7372 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007373}
7374
7375sub get_namespace_additions($)
7376{
7377 my $NameSpaces = $_[0];
7378 my ($Additions, $AddNameSpaceId) = ("", 1);
7379 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7380 {
7381 next if($SkipNameSpaces{$Version}{$NS});
7382 next if(not $NS or $NameSpaces->{$NS}==-1);
7383 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7384 next if($NS=~/\A__/i);
7385 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007386 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007387 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7388 my @NS_Parts = split(/::/, $NS);
7389 next if($#NS_Parts==-1);
7390 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7391 foreach my $NS_Part (@NS_Parts)
7392 {
7393 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7394 $TypeDecl_Suffix .= "}";
7395 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007396 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007397 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7398 $Additions.=" $TypeDecl\n $FuncDecl\n";
7399 $AddNameSpaceId+=1;
7400 }
7401 return $Additions;
7402}
7403
7404sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007405{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007406 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007407 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007408 if($Fmt eq "windows")
7409 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007410 $Path=~s/\//\\/g;
7411 $Path=lc($Path);
7412 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007413 else
7414 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007415 $Path=~s/\\/\//g;
7416 }
7417 return $Path;
7418}
7419
7420sub inc_opt($$)
7421{
7422 my ($Path, $Style) = @_;
7423 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007424 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007425 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007426 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007427 return "-I\"".path_format($Path, "unix")."\"";
7428 }
7429 elsif($OSgroup eq "macos"
7430 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007431 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007432 return "-F".esc(get_dirname($Path));
7433 }
7434 else {
7435 return "-I".esc($Path);
7436 }
7437 }
7438 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007439 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007440 }
7441 return "";
7442}
7443
7444sub platformSpecs($)
7445{
7446 my $LibVersion = $_[0];
7447 my $Arch = getArch($LibVersion);
7448 if($OStarget eq "symbian")
7449 { # options for GCCE compiler
7450 my %Symbian_Opts = map {$_=>1} (
7451 "-D__GCCE__",
7452 "-DUNICODE",
7453 "-fexceptions",
7454 "-D__SYMBIAN32__",
7455 "-D__MARM_INTERWORK__",
7456 "-D_UNICODE",
7457 "-D__S60_50__",
7458 "-D__S60_3X__",
7459 "-D__SERIES60_3X__",
7460 "-D__EPOC32__",
7461 "-D__MARM__",
7462 "-D__EABI__",
7463 "-D__MARM_ARMV5__",
7464 "-D__SUPPORT_CPP_EXCEPTIONS__",
7465 "-march=armv5t",
7466 "-mapcs",
7467 "-mthumb-interwork",
7468 "-DEKA2",
7469 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7470 );
7471 return join(" ", keys(%Symbian_Opts));
7472 }
7473 elsif($OSgroup eq "windows"
7474 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7475 { # add options to MinGW compiler
7476 # to simulate the MSVC compiler
7477 my %MinGW_Opts = map {$_=>1} (
7478 "-D_WIN32",
7479 "-D_STDCALL_SUPPORTED",
7480 "-D__int64=\"long long\"",
7481 "-D__int32=int",
7482 "-D__int16=short",
7483 "-D__int8=char",
7484 "-D__possibly_notnullterminated=\" \"",
7485 "-D__nullterminated=\" \"",
7486 "-D__nullnullterminated=\" \"",
7487 "-D__w64=\" \"",
7488 "-D__ptr32=\" \"",
7489 "-D__ptr64=\" \"",
7490 "-D__forceinline=inline",
7491 "-D__inline=inline",
7492 "-D__uuidof(x)=IID()",
7493 "-D__try=",
7494 "-D__except(x)=",
7495 "-D__declspec(x)=__attribute__((x))",
7496 "-D__pragma(x)=",
7497 "-D_inline=inline",
7498 "-D__forceinline=__inline",
7499 "-D__stdcall=__attribute__((__stdcall__))",
7500 "-D__cdecl=__attribute__((__cdecl__))",
7501 "-D__fastcall=__attribute__((__fastcall__))",
7502 "-D__thiscall=__attribute__((__thiscall__))",
7503 "-D_stdcall=__attribute__((__stdcall__))",
7504 "-D_cdecl=__attribute__((__cdecl__))",
7505 "-D_fastcall=__attribute__((__fastcall__))",
7506 "-D_thiscall=__attribute__((__thiscall__))",
7507 "-DSHSTDAPI_(x)=x",
7508 "-D_MSC_EXTENSIONS",
7509 "-DSECURITY_WIN32",
7510 "-D_MSC_VER=1500",
7511 "-D_USE_DECLSPECS_FOR_SAL",
7512 "-D__noop=\" \"",
7513 "-DDECLSPEC_DEPRECATED=\" \"",
7514 "-D__builtin_alignof(x)=__alignof__(x)",
7515 "-DSORTPP_PASS");
7516 if($Arch eq "x86") {
7517 $MinGW_Opts{"-D_M_IX86=300"}=1;
7518 }
7519 elsif($Arch eq "x86_64") {
7520 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7521 }
7522 elsif($Arch eq "ia64") {
7523 $MinGW_Opts{"-D_M_IA64=300"}=1;
7524 }
7525 return join(" ", keys(%MinGW_Opts));
7526 }
7527 return "";
7528}
7529
7530my %C_Structure = map {$_=>1} (
7531# FIXME: Can't separate union and struct data types before dumping,
7532# so it sometimes cause compilation errors for unknown reason
7533# when trying to declare TYPE* tmp_add_class_N
7534# This is a list of such structures + list of other C structures
7535 "sigval",
7536 "sigevent",
7537 "sigaction",
7538 "sigvec",
7539 "sigstack",
7540 "timeval",
7541 "timezone",
7542 "rusage",
7543 "rlimit",
7544 "wait",
7545 "flock",
7546 "stat",
7547 "_stat",
7548 "stat32",
7549 "_stat32",
7550 "stat64",
7551 "_stat64",
7552 "_stati64",
7553 "if_nameindex",
7554 "usb_device",
7555 "sigaltstack",
7556 "sysinfo",
7557 "timeLocale",
7558 "tcp_debug",
7559 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007560 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007561 "timespec",
7562 "random_data",
7563 "drand48_data",
7564 "_IO_marker",
7565 "_IO_FILE",
7566 "lconv",
7567 "sched_param",
7568 "tm",
7569 "itimerspec",
7570 "_pthread_cleanup_buffer",
7571 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007572 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007573 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007574 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007575 "sigcontext",
7576 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007577 # Mac
7578 "_timex",
7579 "_class_t",
7580 "_category_t",
7581 "_class_ro_t",
7582 "_protocol_t",
7583 "_message_ref_t",
7584 "_super_message_ref_t",
7585 "_ivar_t",
7586 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007587);
7588
7589sub getCompileCmd($$$)
7590{
7591 my ($Path, $Opt, $Inc) = @_;
7592 my $GccCall = $GCC_PATH;
7593 if($Opt) {
7594 $GccCall .= " ".$Opt;
7595 }
7596 $GccCall .= " -x ";
7597 if($OSgroup eq "macos") {
7598 $GccCall .= "objective-";
7599 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007600 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007601 { # compile as "C++" header
7602 # to obtain complete dump using GCC 4.0
7603 $GccCall .= "c++-header";
7604 }
7605 else
7606 { # compile as "C++" source
7607 # GCC 3.3 cannot compile headers
7608 $GccCall .= "c++";
7609 }
7610 if(my $Opts = platformSpecs($Version))
7611 {# platform-specific options
7612 $GccCall .= " ".$Opts;
7613 }
7614 # allow extra qualifications
7615 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007616 $GccCall .= " -fpermissive";
7617 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007618 if($NoStdInc)
7619 {
7620 $GccCall .= " -nostdinc";
7621 $GccCall .= " -nostdinc++";
7622 }
7623 if($CompilerOptions{$Version})
7624 { # user-defined options
7625 $GccCall .= " ".$CompilerOptions{$Version};
7626 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007627 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007628 if($Inc)
7629 { # include paths
7630 $GccCall .= " ".$Inc;
7631 }
7632 return $GccCall;
7633}
7634
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007635sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007636{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007637 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007638 my %HeaderElems = (
7639 # Types
7640 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007641 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007642 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
7643 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007644 "time.h" => ["time_t"],
7645 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007646 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
7647 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007648 "stdbool.h" => ["_Bool"],
7649 "rpc/xdr.h" => ["bool_t"],
7650 "in_systm.h" => ["n_long", "n_short"],
7651 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04007652 "arpa/inet.h" => ["fw_src", "ip_src"],
7653 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007654 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007655 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007656 );
7657 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007658 foreach (keys(%HeaderElems))
7659 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007660 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007661 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007662 }
7663 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007664 my %Types = ();
7665 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
7666 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007667 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007668 }
7669 if(keys(%Types))
7670 {
7671 my %AddHeaders = ();
7672 foreach my $Type (keys(%Types))
7673 {
7674 if(my $Header = $AutoPreamble{$Type})
7675 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007676 if(my $Path = identifyHeader($Header, $LibVersion))
7677 {
7678 if(skipHeader($Path, $LibVersion)) {
7679 next;
7680 }
7681 $Path = path_format($Path, $OSgroup);
7682 $AddHeaders{$Path}{"Type"} = $Type;
7683 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007684 }
7685 }
7686 }
7687 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007688 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007689 }
7690 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007691 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007692}
7693
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007694sub checkCTags($)
7695{
7696 my $Path = $_[0];
7697 if(not $Path) {
7698 return;
7699 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007700 my $CTags = undef;
7701
7702 if($OSgroup eq "bsd")
7703 { # use ectags on BSD
7704 $CTags = get_CmdPath("ectags");
7705 if(not $CTags) {
7706 printMsg("WARNING", "can't find \'ectags\' program");
7707 }
7708 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007709 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007710 $CTags = get_CmdPath("ctags");
7711 }
7712 if(not $CTags)
7713 {
7714 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007715 return;
7716 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007717
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007718 if($OSgroup ne "linux")
7719 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007720 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
7721 if($Info!~/exuberant/i)
7722 {
7723 printMsg("WARNING", "incompatible version of \'ctags\' program");
7724 return;
7725 }
7726 }
7727
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007728 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007729 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007730 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007731 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007732 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007733 open(CTAGS, "<", $Out);
7734 while(my $Line = <CTAGS>)
7735 {
7736 chomp($Line);
7737 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007738 if(defined $Intrinsic_Keywords{$Name})
7739 { # noise
7740 next;
7741 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007742 if($Type eq "n")
7743 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007744 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007745 next;
7746 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007747 if(index($Scpe, "struct:")==0) {
7748 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007749 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007750 if(index($Scpe, "namespace:")==0)
7751 {
7752 if($Scpe=~s/\Anamespace://) {
7753 $Name = $Scpe."::".$Name;
7754 }
7755 }
7756 $TUnit_NameSpaces{$Version}{$Name} = 1;
7757 }
7758 elsif($Type eq "p")
7759 {
7760 if(not $Scpe or index($Scpe, "namespace:")==0) {
7761 $TUnit_Funcs{$Version}{$Name} = 1;
7762 }
7763 }
7764 elsif($Type eq "x")
7765 {
7766 if(not $Scpe or index($Scpe, "namespace:")==0) {
7767 $TUnit_Vars{$Version}{$Name} = 1;
7768 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007769 }
7770 }
7771 close(CTAGS);
7772}
7773
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007774sub preChange($$)
7775{
7776 my ($HeaderPath, $IncStr) = @_;
7777
7778 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
7779 my $Content = undef;
7780
7781 if($OStarget eq "windows"
7782 and get_dumpmachine($GCC_PATH)=~/mingw/i
7783 and $MinGWMode{$Version}!=-1)
7784 { # modify headers to compile by MinGW
7785 if(not $Content)
7786 { # preprocessing
7787 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
7788 }
7789 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
7790 { # __asm { ... }
7791 $MinGWMode{$Version}=1;
7792 }
7793 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
7794 { # comments after preprocessing
7795 $MinGWMode{$Version}=1;
7796 }
7797 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
7798 { # 0xffui8
7799 $MinGWMode{$Version}=1;
7800 }
7801
7802 if($MinGWMode{$Version}) {
7803 printMsg("INFO", "Using MinGW compatibility mode");
7804 }
7805 }
7806
7807 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
7808 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
7809 { # rename C++ keywords in C code
7810 # disable this code by -cpp-compatible option
7811 if(not $Content)
7812 { # preprocessing
7813 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
7814 }
7815 my $RegExp_C = join("|", keys(%CppKeywords_C));
7816 my $RegExp_F = join("|", keys(%CppKeywords_F));
7817 my $RegExp_O = join("|", keys(%CppKeywords_O));
7818
7819 my $Detected = undef;
7820
7821 while($Content=~s/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*(\,|\)|\;|\-\>|\.|\:\s*\d))/$1$2c99_$3$4/g)
7822 { # MATCH:
7823 # int foo(int new, int class, int (*new)(int));
7824 # unsigned private: 8;
7825 # DO NOT MATCH:
7826 # #pragma GCC visibility push(default)
7827 $CppMode{$Version} = 1;
7828 $Detected = "$1$2$3$4" if(not defined $Detected);
7829 }
7830 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
7831 { # MATCH:
7832 # int delete(...);
7833 # int explicit(...);
7834 # DO NOT MATCH:
7835 # void operator delete(...)
7836 $CppMode{$Version} = 1;
7837 $Detected = "$1$2$3" if(not defined $Detected);
7838 }
7839 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
7840 { # MATCH:
7841 # int bool;
7842 # DO NOT MATCH:
7843 # bool X;
7844 # return *this;
7845 # throw;
7846 $CppMode{$Version} = 1;
7847 $Detected = "$1$2$3" if(not defined $Detected);
7848 }
7849 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
7850 { # MATCH:
7851 # int operator(...);
7852 # DO NOT MATCH:
7853 # int operator()(...);
7854 $CppMode{$Version} = 1;
7855 $Detected = "$1$2$3" if(not defined $Detected);
7856 }
7857 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
7858 { # MATCH:
7859 # int foo(int operator);
7860 # int foo(int operator, int other);
7861 # DO NOT MATCH:
7862 # int operator,(...);
7863 $CppMode{$Version} = 1;
7864 $Detected = "$1$2$3" if(not defined $Detected);
7865 }
7866 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
7867 { # MATCH:
7868 # int foo(gboolean *bool);
7869 # DO NOT MATCH:
7870 # void setTabEnabled(int index, bool);
7871 $CppMode{$Version} = 1;
7872 $Detected = "$1$2$3" if(not defined $Detected);
7873 }
7874 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
7875 { # MATCH:
7876 # int foo(int* this);
7877 # int bar(int this);
7878 # int baz(int throw);
7879 # DO NOT MATCH:
7880 # foo(X, this);
7881 $CppMode{$Version} = 1;
7882 $Detected = "$1$2$3$4" if(not defined $Detected);
7883 }
7884 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
7885 { # MATCH:
7886 # struct template {...};
7887 # extern template foo(...);
7888 $CppMode{$Version} = 1;
7889 $Detected = "$1$2" if(not defined $Detected);
7890 }
7891
7892 if($CppMode{$Version} == 1)
7893 {
7894 if($Debug)
7895 {
7896 $Detected=~s/\A\s+//g;
7897 printMsg("INFO", "Detected code: \"$Detected\"");
7898 }
7899 }
7900
7901 # remove typedef enum NAME NAME;
7902 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
7903 my $N = 0;
7904 while($N<=$#FwdTypedefs-1)
7905 {
7906 my $S = $FwdTypedefs[$N];
7907 if($S eq $FwdTypedefs[$N+1])
7908 {
7909 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007910 $CppMode{$Version} = 1;
7911
7912 if($Debug) {
7913 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
7914 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007915 }
7916 $N+=2;
7917 }
7918
7919 if($CppMode{$Version}==1) {
7920 printMsg("INFO", "Using C++ compatibility mode");
7921 }
7922 }
7923
7924 if($CppMode{$Version}==1
7925 or $MinGWMode{$Version}==1)
7926 {
7927 my $IPath = $TMP_DIR."/dump$Version.i";
7928 writeFile($IPath, $Content);
7929 return $IPath;
7930 }
7931
7932 return undef;
7933}
7934
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007935sub getDump()
7936{
7937 if(not $GCC_PATH) {
7938 exitStatus("Error", "internal error - GCC path is not set");
7939 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007940
7941 my @Headers = keys(%{$Registered_Headers{$Version}});
7942 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
7943
7944 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
7945
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007946 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007947 my $HeaderPath = $TmpHeaderPath;
7948
7949 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007950 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007951 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
7952 {
7953 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007954 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007955 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007956 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007957 foreach my $HPath (@{$Include_Preamble{$Version}}) {
7958 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007959 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007960 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007961 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007962 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
7963 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
7964 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007965 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007966 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007967
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007968 if($ExtraInfo)
7969 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007970 if($IncludeString) {
7971 writeFile($ExtraInfo."/include-string", $IncludeString);
7972 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04007973 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
7974 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007975
7976 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
7977 {
7978 my $REDIR = "";
7979 foreach my $P1 (sort @Redirects) {
7980 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
7981 }
7982 writeFile($ExtraInfo."/include-redirect", $REDIR);
7983 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007984 }
7985
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007986 if(not keys(%{$TargetHeaders{$Version}}))
7987 { # Target headers
7988 addTargetHeaders($Version);
7989 }
7990
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007991 # clean memory
7992 %RecursiveIncludes = ();
7993 %Header_Include_Prefix = ();
7994 %Header_Includes = ();
7995
7996 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007997 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007998 delete($Cache{"detect_header_includes"});
7999 delete($Cache{"selectSystemHeader"});
8000
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008001 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008002 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8003 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008004
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008005 if($ExtraInfo)
8006 { # extra information for other tools
8007 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8008 }
8009
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008010 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008011 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008012 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008013
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008014 if($COMMON_LANGUAGE{$Version} eq "C++") {
8015 checkCTags($Pre);
8016 }
8017
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008018 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8019 { # try to correct the preprocessor output
8020 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008021 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008022
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008023 if($COMMON_LANGUAGE{$Version} eq "C++")
8024 { # add classes and namespaces to the dump
8025 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008026 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008027 or $MinGWMode{$Version}==1) {
8028 $CHdump .= " -fpreprocessed";
8029 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008030 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008031 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008032 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008033 chdir($ORIG_DIR);
8034 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8035 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008036 my $Content = readFile($ClassDump);
8037 foreach my $ClassInfo (split(/\n\n/, $Content))
8038 {
8039 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8040 {
8041 my $CName = $1;
8042 next if($CName=~/\A(__|_objc_|_opaque_)/);
8043 $TUnit_NameSpaces{$Version}{$CName} = -1;
8044 if($CName=~/\A[\w:]+\Z/)
8045 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008046 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008047 }
8048 if($CName=~/(\w[\w:]*)::/)
8049 { # namespaces
8050 my $NS = $1;
8051 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8052 $TUnit_NameSpaces{$Version}{$NS} = 1;
8053 }
8054 }
8055 }
8056 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8057 { # read v-tables (advanced approach)
8058 my ($CName, $VTable) = ($1, $2);
8059 $ClassVTable_Content{$Version}{$CName} = $VTable;
8060 }
8061 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008062 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8063 { # add user-defined namespaces
8064 $TUnit_NameSpaces{$Version}{$NS} = 1;
8065 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008066 if($Debug)
8067 { # debug mode
8068 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008069 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008070 }
8071 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008072 }
8073
8074 # add namespaces and classes
8075 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8076 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008077 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008078 }
8079 # some GCC versions don't include class methods to the TU dump by default
8080 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008081 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008082 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8083 {
8084 next if($C_Structure{$CName});
8085 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008086 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008087 if(not $Force and $GCC_44
8088 and $OSgroup eq "linux")
8089 { # optimization for linux with GCC >= 4.4
8090 # disable this code by -force option
8091 if(index($CName, "::")!=-1)
8092 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008093 next;
8094 }
8095 }
8096 else
8097 {
8098 if($CName=~/\A(.+)::[^:]+\Z/
8099 and $TUnit_Classes{$Version}{$1})
8100 { # classes inside other classes
8101 next;
8102 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008103 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008104 if(defined $TUnit_Funcs{$Version}{$CName})
8105 { # the same name for a function and type
8106 next;
8107 }
8108 if(defined $TUnit_Vars{$Version}{$CName})
8109 { # the same name for a variable and type
8110 next;
8111 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008112 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8113 }
8114 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008115 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008116 }
8117 }
8118 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8119 # create TU dump
8120 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008121 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008122 or $MinGWMode{$Version}==1) {
8123 $TUdump .= " -fpreprocessed";
8124 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008125 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008126 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8127 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008128 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008129 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008130 if($?)
8131 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008132 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008133 { # try to recompile
8134 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008135 if($CppMode{$Version}==1
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008136 and index($Errors, "c99_")!=-1)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008137 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008138 $CppMode{$Version}=-1;
8139 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008140 resetLogging($Version);
8141 $TMP_DIR = tempdir(CLEANUP=>1);
8142 return getDump();
8143 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008144 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008145 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008146 { # add auto preamble headers and try again
8147 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008148 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008149 foreach my $Num (0 .. $#Headers)
8150 {
8151 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008152 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8153 {
8154 push_U($Include_Preamble{$Version}, $Path);
8155 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008156 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008157 }
8158 resetLogging($Version);
8159 $TMP_DIR = tempdir(CLEANUP=>1);
8160 return getDump();
8161 }
8162 elsif($Cpp0xMode{$Version}!=-1
8163 and ($Errors=~/\Q-std=c++0x\E/
8164 or $Errors=~/is not a class or namespace/))
8165 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008166 if(check_gcc($GCC_PATH, "4.6"))
8167 {
8168 $Cpp0xMode{$Version}=-1;
8169 printMsg("INFO", "Enabling c++0x mode");
8170 resetLogging($Version);
8171 $TMP_DIR = tempdir(CLEANUP=>1);
8172 $CompilerOptions{$Version} .= " -std=c++0x";
8173 return getDump();
8174 }
8175 else {
8176 printMsg("WARNING", "Probably c++0x construction detected");
8177 }
8178
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008179 }
8180 elsif($MinGWMode{$Version}==1)
8181 { # disable MinGW mode and try again
8182 $MinGWMode{$Version}=-1;
8183 resetLogging($Version);
8184 $TMP_DIR = tempdir(CLEANUP=>1);
8185 return getDump();
8186 }
8187 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008188 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008189 else {
8190 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008191 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008192 printMsg("ERROR", "some errors occurred when compiling headers");
8193 printErrorLog($Version);
8194 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008195 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008196 }
8197 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008198 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008199 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008200
8201 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8202 return $TUs[0];
8203 }
8204 else
8205 {
8206 my $Msg = "can't compile header(s)";
8207 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8208 $Msg .= "\nDid you install G++?";
8209 }
8210 exitStatus("Cannot_Compile", $Msg);
8211 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008212}
8213
8214sub cmd_file($)
8215{
8216 my $Path = $_[0];
8217 return "" if(not $Path or not -e $Path);
8218 if(my $CmdPath = get_CmdPath("file")) {
8219 return `$CmdPath -b \"$Path\"`;
8220 }
8221 return "";
8222}
8223
8224sub getIncString($$)
8225{
8226 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008227 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008228 my $String = "";
8229 foreach (@{$ArrRef}) {
8230 $String .= " ".inc_opt($_, $Style);
8231 }
8232 return $String;
8233}
8234
8235sub getIncPaths(@)
8236{
8237 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008238 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008239 if($INC_PATH_AUTODETECT{$Version})
8240 { # auto-detecting dependencies
8241 my %Includes = ();
8242 foreach my $HPath (@HeaderPaths)
8243 {
8244 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8245 {
8246 if($Skip_Include_Paths{$Version}{$Dir}) {
8247 next;
8248 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008249 if($SystemRoot)
8250 {
8251 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8252 next;
8253 }
8254 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008255 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008256 }
8257 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008258 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008259 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008260 }
8261 }
8262 else
8263 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008264 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008265 }
8266 return \@IncPaths;
8267}
8268
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008269sub push_U($@)
8270{ # push unique
8271 if(my $Array = shift @_)
8272 {
8273 if(@_)
8274 {
8275 my %Exist = map {$_=>1} @{$Array};
8276 foreach my $Elem (@_)
8277 {
8278 if(not defined $Exist{$Elem})
8279 {
8280 push(@{$Array}, $Elem);
8281 $Exist{$Elem} = 1;
8282 }
8283 }
8284 }
8285 }
8286}
8287
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008288sub callPreprocessor($$$)
8289{
8290 my ($Path, $Inc, $LibVersion) = @_;
8291 return "" if(not $Path or not -f $Path);
8292 my $IncludeString=$Inc;
8293 if(not $Inc) {
8294 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8295 }
8296 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008297 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008298 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008299 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008300}
8301
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008302sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008303{ # native "find" is much faster than File::Find (~6x)
8304 # also the File::Find doesn't support --maxdepth N option
8305 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008306 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008307 return () if(not $Path or not -e $Path);
8308 if($OSgroup eq "windows")
8309 {
8310 my $DirCmd = get_CmdPath("dir");
8311 if(not $DirCmd) {
8312 exitStatus("Not_Found", "can't find \"dir\" command");
8313 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008314 $Path = get_abs_path($Path);
8315 $Path = path_format($Path, $OSgroup);
8316 my $Cmd = $DirCmd." \"$Path\" /B /O";
8317 if($MaxDepth!=1) {
8318 $Cmd .= " /S";
8319 }
8320 if($Type eq "d") {
8321 $Cmd .= " /AD";
8322 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008323 elsif($Type eq "f") {
8324 $Cmd .= " /A-D";
8325 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008326 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008327 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008328 {
8329 if(not $UseRegex)
8330 { # FIXME: how to search file names in MS shell?
8331 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008332 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008333 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008334 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008335 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008336 }
8337 my @AbsPaths = ();
8338 foreach my $File (@Files)
8339 {
8340 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008341 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008342 }
8343 if($Type eq "f" and not -f $File)
8344 { # skip dirs
8345 next;
8346 }
8347 push(@AbsPaths, path_format($File, $OSgroup));
8348 }
8349 if($Type eq "d") {
8350 push(@AbsPaths, $Path);
8351 }
8352 return @AbsPaths;
8353 }
8354 else
8355 {
8356 my $FindCmd = get_CmdPath("find");
8357 if(not $FindCmd) {
8358 exitStatus("Not_Found", "can't find a \"find\" command");
8359 }
8360 $Path = get_abs_path($Path);
8361 if(-d $Path and -l $Path
8362 and $Path!~/\/\Z/)
8363 { # for directories that are symlinks
8364 $Path.="/";
8365 }
8366 my $Cmd = $FindCmd." \"$Path\"";
8367 if($MaxDepth) {
8368 $Cmd .= " -maxdepth $MaxDepth";
8369 }
8370 if($Type) {
8371 $Cmd .= " -type $Type";
8372 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008373 if($Name and not $UseRegex)
8374 { # wildcards
8375 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008376 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008377 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008378 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008379 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8380 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008381 my @Files = split(/\n/, $Res);
8382 if($Name and $UseRegex)
8383 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008384 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008385 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008386 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008387 }
8388}
8389
8390sub unpackDump($)
8391{
8392 my $Path = $_[0];
8393 return "" if(not $Path or not -e $Path);
8394 $Path = get_abs_path($Path);
8395 $Path = path_format($Path, $OSgroup);
8396 my ($Dir, $FileName) = separate_path($Path);
8397 my $UnpackDir = $TMP_DIR."/unpack";
8398 rmtree($UnpackDir);
8399 mkpath($UnpackDir);
8400 if($FileName=~s/\Q.zip\E\Z//g)
8401 { # *.zip
8402 my $UnzipCmd = get_CmdPath("unzip");
8403 if(not $UnzipCmd) {
8404 exitStatus("Not_Found", "can't find \"unzip\" command");
8405 }
8406 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008407 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008408 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008409 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008410 }
8411 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008412 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008413 if(not @Contents) {
8414 exitStatus("Error", "can't extract \'$Path\'");
8415 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008416 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008417 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008418 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008419 { # *.tar.gz
8420 if($OSgroup eq "windows")
8421 { # -xvzf option is not implemented in tar.exe (2003)
8422 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8423 my $TarCmd = get_CmdPath("tar");
8424 if(not $TarCmd) {
8425 exitStatus("Not_Found", "can't find \"tar\" command");
8426 }
8427 my $GzipCmd = get_CmdPath("gzip");
8428 if(not $GzipCmd) {
8429 exitStatus("Not_Found", "can't find \"gzip\" command");
8430 }
8431 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008432 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008433 if($?) {
8434 exitStatus("Error", "can't extract \'$Path\'");
8435 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008436 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008437 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008438 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008439 }
8440 chdir($ORIG_DIR);
8441 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008442 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008443 if(not @Contents) {
8444 exitStatus("Error", "can't extract \'$Path\'");
8445 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008446 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008447 }
8448 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008449 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008450 my $TarCmd = get_CmdPath("tar");
8451 if(not $TarCmd) {
8452 exitStatus("Not_Found", "can't find \"tar\" command");
8453 }
8454 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008455 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008456 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008457 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008458 }
8459 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008460 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008461 if(not @Contents) {
8462 exitStatus("Error", "can't extract \'$Path\'");
8463 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008464 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008465 }
8466 }
8467}
8468
8469sub createArchive($$)
8470{
8471 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008472 if(not $To) {
8473 $To = ".";
8474 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008475 if(not $Path or not -e $Path
8476 or not -d $To) {
8477 return "";
8478 }
8479 my ($From, $Name) = separate_path($Path);
8480 if($OSgroup eq "windows")
8481 { # *.zip
8482 my $ZipCmd = get_CmdPath("zip");
8483 if(not $ZipCmd) {
8484 exitStatus("Not_Found", "can't find \"zip\"");
8485 }
8486 my $Pkg = $To."/".$Name.".zip";
8487 unlink($Pkg);
8488 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008489 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008490 if($?)
8491 { # cannot allocate memory (or other problems with "zip")
8492 unlink($Path);
8493 exitStatus("Error", "can't pack the ABI dump: ".$!);
8494 }
8495 chdir($ORIG_DIR);
8496 unlink($Path);
8497 return $Pkg;
8498 }
8499 else
8500 { # *.tar.gz
8501 my $TarCmd = get_CmdPath("tar");
8502 if(not $TarCmd) {
8503 exitStatus("Not_Found", "can't find \"tar\"");
8504 }
8505 my $GzipCmd = get_CmdPath("gzip");
8506 if(not $GzipCmd) {
8507 exitStatus("Not_Found", "can't find \"gzip\"");
8508 }
8509 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8510 unlink($Pkg);
8511 chdir($From);
8512 system($TarCmd, "-czf", $Pkg, $Name);
8513 if($?)
8514 { # cannot allocate memory (or other problems with "tar")
8515 unlink($Path);
8516 exitStatus("Error", "can't pack the ABI dump: ".$!);
8517 }
8518 chdir($ORIG_DIR);
8519 unlink($Path);
8520 return $To."/".$Name.".tar.gz";
8521 }
8522}
8523
8524sub is_header_file($)
8525{
8526 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8527 return $_[0];
8528 }
8529 return 0;
8530}
8531
8532sub is_not_header($)
8533{
8534 if($_[0]=~/\.\w+\Z/
8535 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8536 return 1;
8537 }
8538 return 0;
8539}
8540
8541sub is_header($$$)
8542{
8543 my ($Header, $UserDefined, $LibVersion) = @_;
8544 return 0 if(-d $Header);
8545 if(-f $Header) {
8546 $Header = get_abs_path($Header);
8547 }
8548 else
8549 {
8550 if(is_abs($Header))
8551 { # incorrect absolute path
8552 return 0;
8553 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008554 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008555 $Header = $HPath;
8556 }
8557 else
8558 { # can't find header
8559 return 0;
8560 }
8561 }
8562 if($Header=~/\.\w+\Z/)
8563 { # have an extension
8564 return is_header_file($Header);
8565 }
8566 else
8567 {
8568 if($UserDefined==2)
8569 { # specified on the command line
8570 if(cmd_file($Header)!~/HTML|XML/i) {
8571 return $Header;
8572 }
8573 }
8574 elsif($UserDefined)
8575 { # specified in the XML-descriptor
8576 # header file without an extension
8577 return $Header;
8578 }
8579 else
8580 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008581 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008582 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008583 { # !~/HTML|XML|shared|dynamic/i
8584 return $Header;
8585 }
8586 }
8587 }
8588 return 0;
8589}
8590
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008591sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008592{
8593 my $LibVersion = $_[0];
8594 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
8595 {
8596 my $RegDir = get_dirname($RegHeader);
8597 $TargetHeaders{$LibVersion}{get_filename($RegHeader)}=1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008598
8599 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
8600 detect_recursive_includes($RegHeader, $LibVersion);
8601 }
8602
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008603 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
8604 {
8605 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008606
8607 if(familiarDirs($Dir, $RegDir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008608 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
8609 { # in the same directory or included by #include "..."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008610 $TargetHeaders{$LibVersion}{get_filename($RecInc)}=1;
8611 }
8612 }
8613 }
8614}
8615
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008616sub familiarDirs($$)
8617{
8618 my ($D1, $D2) = @_;
8619 if($D1 eq $D2) {
8620 return 1;
8621 }
8622 while($D1=~s/[\/\\]+.*?\Z//)
8623 {
8624 $D2=~s/[\/\\]+.*?\Z//;
8625 if($D1 eq "/usr/include") {
8626 return 0;
8627 }
8628 if($D1 eq $D2) {
8629 return 1;
8630 }
8631 }
8632 return 0;
8633}
8634
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008635sub readHeaders($)
8636{
8637 $Version = $_[0];
8638 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
8639 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008640 if($Debug)
8641 { # debug mode
8642 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008643 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008644 }
8645 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008646}
8647
8648sub prepareTypes($)
8649{
8650 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008651 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008652 { # support for old ABI dumps
8653 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008654 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008655 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008656 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
8657 if($TName=~/\A(\w+)::(\w+)/) {
8658 my ($P1, $P2) = ($1, $2);
8659 if($P1 eq $P2) {
8660 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008661 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008662 else {
8663 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
8664 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008665 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008666 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008667 }
8668 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008669 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008670 { # support for old ABI dumps
8671 # V < 2.5: array size == "number of elements"
8672 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008673 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008674 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008675 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008676 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008677 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008678 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008679 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008680 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008681 $Size *= $Base{"Size"};
8682 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008683 }
8684 else
8685 { # array[] is a pointer
8686 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008687 }
8688 }
8689 }
8690 }
8691 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008692 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008693 { # support for old ABI dumps
8694 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008695 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008696 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008697 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008698 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008699 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008700 my %Type = get_Type($TypeId, $LibVersion);
8701 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
8702 my %Type2 = get_Type($TypeId_2, $V2);
8703 if($Type{"Size"} ne $Type2{"Size"}) {
8704 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008705 }
8706 }
8707 }
8708 }
8709}
8710
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008711sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008712{
8713 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008714
8715 if(not keys(%{$SymbolInfo{$LibVersion}}))
8716 { # check if input is valid
8717 if(not $ExtendedCheck and not $CheckObjectsOnly)
8718 {
8719 if($CheckHeadersOnly) {
8720 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
8721 }
8722 else {
8723 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
8724 }
8725 }
8726 }
8727
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008728 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008729 if(not checkDump(1, "2.10")
8730 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008731 { # different formats
8732 $Remangle = 1;
8733 }
8734 if($CheckHeadersOnly)
8735 { # different languages
8736 if($UserLang)
8737 { # --lang=LANG for both versions
8738 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
8739 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
8740 {
8741 if($UserLang eq "C++")
8742 { # remangle symbols
8743 $Remangle = 1;
8744 }
8745 elsif($UserLang eq "C")
8746 { # remove mangling
8747 $Remangle = -1;
8748 }
8749 }
8750 }
8751 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008752
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008753 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008754 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008755 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04008756 { # support for old ABI dumps
8757 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
8758 {
8759 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
8760 {
8761 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
8762 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008763 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04008764 if(defined $DVal and $DVal ne "")
8765 {
8766 if($TName eq "char") {
8767 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
8768 }
8769 elsif($TName eq "bool") {
8770 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
8771 }
8772 }
8773 }
8774 }
8775 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008776 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008777 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008778 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
8779 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008780 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008781 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
8782 # + support for old ABI dumps
8783 next;
8784 }
8785 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008786 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008787 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008788 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008789 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008790
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008791 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008792 if(not checkDump(1, "2.12")
8793 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008794 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008795 if($ShortName eq "operator>>")
8796 {
8797 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
8798 { # corrected mangling of operator>>
8799 $SRemangle = 1;
8800 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008801 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008802 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
8803 {
8804 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
8805 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
8806 { # corrected mangling of const global data
8807 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
8808 # and incorrectly mangled by old ACC versions
8809 $SRemangle = 1;
8810 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008811 }
8812 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008813 if(not $CheckHeadersOnly)
8814 { # support for old ABI dumps
8815 if(not checkDump(1, "2.17")
8816 or not checkDump(2, "2.17"))
8817 {
8818 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
8819 {
8820 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
8821 {
8822 if(link_symbol($ShortName, $LibVersion, "-Deps"))
8823 {
8824 $MnglName = $ShortName;
8825 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
8826 }
8827 }
8828 }
8829 }
8830 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008831 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008832 { # support for old ABI dumps: some symbols are not mangled in old dumps
8833 # mangle both sets of symbols (old and new)
8834 # NOTE: remangling all symbols by the same mangler
8835 if($MnglName=~/\A_ZN(V|)K/)
8836 { # mangling may be incorrect on old ABI dumps
8837 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008838 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008839 }
8840 if($MnglName=~/\A_ZN(K|)V/)
8841 { # mangling may be incorrect on old ABI dumps
8842 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008843 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008844 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008845 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
8846 or (not $ClassID and $CheckHeadersOnly)
8847 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
8848 { # support for old ABI dumps, GCC >= 4.0
8849 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008850 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008851 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008852 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008853 $MangledNames{$LibVersion}{$MnglName} = 1;
8854 }
8855 }
8856 }
8857 elsif($Remangle==-1)
8858 { # remove mangling
8859 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008860 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008861 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008862 if(not $MnglName) {
8863 next;
8864 }
8865 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
8866 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008867 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
8868
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008869 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008870 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008871 { # support for old dumps
8872 # add "Volatile" attribute
8873 if($MnglName=~/_Z(K|)V/) {
8874 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
8875 }
8876 }
8877 # symbol and its symlink have same signatures
8878 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008879 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008880 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008881
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008882 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
8883 {
8884 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
8885 if($SymVer{$LibVersion}{$Alias}) {
8886 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
8887 }
8888 }
8889
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008890 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008891 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008892 }
8893 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
8894 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
8895 }
8896 if($ExtendedCheck)
8897 { # --ext option
8898 addExtension($LibVersion);
8899 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008900
8901 # clean memory
8902 delete($SymbolInfo{$LibVersion});
8903
8904 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008905 { # detect allocable classes with public exported constructors
8906 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008907 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008908 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008909 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008910 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008911 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
8912 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008913 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008914 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008915 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008916 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008917 $AllocableClass{$LibVersion}{$ClassName} = 1;
8918 }
8919 }
8920 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008921 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008922 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008923 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008924 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008925 if($CheckHeadersOnly)
8926 {
8927 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
8928 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
8929 { # all symbols except non-virtual inline
8930 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
8931 }
8932 }
8933 else {
8934 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008935 }
8936 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008937 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008938 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008939 }
8940 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008941 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008942 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008943 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008944 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008945 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008946 if(defined $Base{"Type"}
8947 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008948 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008949 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008950 if($Name=~/<([^<>\s]+)>/)
8951 {
8952 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
8953 $ReturnedClass{$LibVersion}{$Tid} = 1;
8954 }
8955 }
8956 else {
8957 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
8958 }
8959 }
8960 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008961 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008962 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008963 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008964 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008965 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008966 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008967 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008968 if($Base{"Type"}=~/Struct|Class/)
8969 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008970 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008971 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
8972 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008973 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008974 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008975 }
8976 }
8977 }
8978 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008979
8980 # mapping {short name => symbols}
8981 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008982 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008983 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008984 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008985 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008986 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008987 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008988 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008989 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
8990 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008991 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008992 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008993 }
8994 }
8995 }
8996 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008997
8998 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008999 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009000 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009001 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009002 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009003 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9004 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009005 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009006 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009007 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009008 $ClassNames{$LibVersion}{$TName} = 1;
9009 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009010 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009011 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9012 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009013 }
9014 }
9015 }
9016 }
9017 }
9018}
9019
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009020sub register_TypeUsage($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009021{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009022 my ($TypeId, $LibVersion) = @_;
9023 if(not $TypeId) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009024 return 0;
9025 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009026 if($UsedType{$LibVersion}{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009027 { # already registered
9028 return 1;
9029 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009030 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009031 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009032 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009033 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|MethodPtr|FieldPtr|Enum)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009034 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009035 $UsedType{$LibVersion}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009036 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009037 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009038 foreach my $BaseId (keys(%{$TInfo{"Base"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009039 { # register base classes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009040 register_TypeUsage($BaseId, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009041 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009042 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9043 {
9044 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9045 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009046 register_TypeUsage($TTid, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009047 }
9048 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009049 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009050 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009051 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009052 if(my $MTid = $TInfo{"Memb"}{$Memb_Pos}{"type"}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009053 register_TypeUsage($MTid, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009054 }
9055 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009056 if($TInfo{"Type"} eq "FuncPtr"
9057 or $TInfo{"Type"} eq "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009058 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009059 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009060 register_TypeUsage($RTid, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009061 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009062 foreach my $Memb_Pos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009063 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009064 if(my $MTid = $TInfo{"Param"}{$Memb_Pos}{"type"}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009065 register_TypeUsage($MTid, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009066 }
9067 }
9068 }
9069 return 1;
9070 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009071 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009072 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009073 $UsedType{$LibVersion}{$TypeId} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009074 register_TypeUsage($TInfo{"BaseType"}, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009075 return 1;
9076 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009077 elsif($TInfo{"Type"} eq "Intrinsic")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009078 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009079 $UsedType{$LibVersion}{$TypeId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009080 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009081 }
9082 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009083 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009084}
9085
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009086sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009087{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009088 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9089
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009090 if($Level eq "Dump")
9091 {
9092 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9093 { # TODO: check if this symbol is from
9094 # base classes of other target symbols
9095 return 1;
9096 }
9097 }
9098
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009099 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9100 { # stdc++ interfaces
9101 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009102 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009103
9104 my $Target = 0;
9105 if(my $Header = $SInfo->{"Header"}) {
9106 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9107 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009108 if($ExtendedCheck)
9109 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009110 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009111 $Target = 1;
9112 }
9113 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009114 if($CheckHeadersOnly)
9115 {
9116 if($Target)
9117 {
9118 if($Level eq "Dump")
9119 { # dumped
9120 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009121 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009122 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009123 return 1;
9124 }
9125 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009126 else {
9127 return 1;
9128 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009129 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009130 elsif($Level eq "Source")
9131 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009132 return 1;
9133 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009134 elsif($Level eq "Binary")
9135 { # checked
9136 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9137 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9138 return 1;
9139 }
9140 }
9141 }
9142 }
9143 else
9144 { # library is available
9145 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9146 { # exported symbols
9147 return 1;
9148 }
9149 if($Level eq "Dump")
9150 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009151 if($BinaryOnly)
9152 {
9153 if($SInfo->{"Data"})
9154 {
9155 if($Target) {
9156 return 1;
9157 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009158 }
9159 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009160 else
9161 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009162 if($Target) {
9163 return 1;
9164 }
9165 }
9166 }
9167 elsif($Level eq "Source")
9168 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009169 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
9170 or isInLineInst($Symbol, $SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009171 { # skip LOCAL symbols
9172 if($Target) {
9173 return 1;
9174 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009175 }
9176 }
9177 elsif($Level eq "Binary")
9178 { # checked
9179 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9180 {
9181 if($Target) {
9182 return 1;
9183 }
9184 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009185 }
9186 }
9187 return 0;
9188}
9189
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009190sub cleanDump($)
9191{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009192 my $LibVersion = $_[0];
9193 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9194 {
9195 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
9196 if(not $MnglName) {
9197 delete($SymbolInfo{$LibVersion}{$InfoId});
9198 next;
9199 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009200 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009201 if(not $ShortName) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009202 delete($SymbolInfo{$LibVersion}{$InfoId});
9203 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009204 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009205 if($MnglName eq $ShortName)
9206 { # remove duplicate data
9207 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009208 }
9209 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9210 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9211 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009212 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9213 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9214 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009215 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009216 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009217 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009218 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009219 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009220 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009221 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9222 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9223 }
9224 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009225 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9226 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9227 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009228 }
9229}
9230
9231sub selectType($$)
9232{
9233 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009234
9235 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9236 {
9237 if(defined $TypeInfo{$LibVersion}{$Dupl})
9238 {
9239 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9240 { # duplicate
9241 return 0;
9242 }
9243 }
9244 }
9245
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009246 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9247 {
9248 if(not isBuiltIn($THeader))
9249 {
9250 if($TypeInfo{$LibVersion}{$Tid}{"Type"}=~/Class|Struct|Union|Enum|Typedef/)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009251 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009252 if(not isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"}))
9253 {
9254 if(is_target_header($THeader, $LibVersion))
9255 { # from target headers
9256 if(not selfTypedef($Tid, $LibVersion)) {
9257 return 1;
9258 }
9259 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009260 }
9261 }
9262 }
9263 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009264 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009265}
9266
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009267sub removeUnused($$)
9268{ # remove unused data types from the ABI dump
9269 my ($LibVersion, $Kind) = @_;
9270 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9271 {
9272 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9273 if(my $RTid = $FuncInfo{"Return"}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009274 register_TypeUsage($RTid, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009275 }
9276 if(my $FCid = $FuncInfo{"Class"})
9277 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009278 register_TypeUsage($FCid, $LibVersion);
9279 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009280 { # register "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009281 $UsedType{$LibVersion}{$ThisId} = 1;
9282 if(my %ThisType = get_Type($ThisId, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009283 register_TypeUsage($ThisType{"BaseType"}, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009284 }
9285 }
9286 }
9287 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9288 {
9289 if(my $PTid = $FuncInfo{"Param"}{$PPos}{"type"}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009290 register_TypeUsage($PTid, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009291 }
9292 }
9293 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9294 {
9295 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9296 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009297 register_TypeUsage($TTid, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009298 }
9299 }
9300 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009301 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
9302 {
9303 if($UsedType{$LibVersion}{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009304 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009305 next;
9306 }
9307
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009308 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009309 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009310 if(selectType($Tid, $LibVersion)) {
9311 register_TypeUsage($Tid, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009312 }
9313 }
9314 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009315 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
9316 { # remove unused types
9317 if($UsedType{$LibVersion}{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009318 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009319 next;
9320 }
9321 # remove type
9322 delete($TypeInfo{$LibVersion}{$Tid});
9323 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009324
9325 # clean memory
9326 %UsedType = ();
9327}
9328
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009329sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009330{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009331 my ($TypeId, $LibVersion) = @_;
9332 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009333 if($Type{"Type"} eq "Typedef")
9334 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009335 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009336 if($Base{"Type"}=~/Class|Struct/)
9337 {
9338 if($Type{"Name"} eq $Base{"Name"}) {
9339 return 1;
9340 }
9341 elsif($Type{"Name"}=~/::(\w+)\Z/)
9342 {
9343 if($Type{"Name"} eq $Base{"Name"}."::".$1)
9344 { # QPointer<QWidget>::QPointer
9345 return 1;
9346 }
9347 }
9348 }
9349 }
9350 return 0;
9351}
9352
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009353sub addExtension($)
9354{
9355 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009356 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009357 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009358 if(selectType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009359 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009360 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9361 $TName=~s/\A(struct|union|class|enum) //;
9362 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009363
9364 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
9365 "Header" => "extended.h",
9366 "ShortName" => $Symbol,
9367 "MnglName" => $Symbol,
9368 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
9369 );
9370
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009371 $ExtendedSymbols{$Symbol} = 1;
9372 $CheckedSymbols{"Binary"}{$Symbol} = 1;
9373 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009374 }
9375 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009376 $ExtendedSymbols{"external_func_0"} = 1;
9377 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
9378 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009379}
9380
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009381sub findMethod($$$)
9382{
9383 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009384 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009385 {
9386 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
9387 return $VirtMethodInClass;
9388 }
9389 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
9390 return $VirtMethodInBaseClasses;
9391 }
9392 }
9393 return "";
9394}
9395
9396sub findMethod_Class($$$)
9397{
9398 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009399 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009400 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
9401 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
9402 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
9403 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
9404 { # search for interface with the same parameters suffix (overridden)
9405 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
9406 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04009407 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
9408 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009409 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
9410 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009411 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
9412 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
9413 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
9414 return $Candidate;
9415 }
9416 }
9417 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04009418 else
9419 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009420 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
9421 return $Candidate;
9422 }
9423 }
9424 }
9425 }
9426 return "";
9427}
9428
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009429sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009430{
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009431 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009432 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009433 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009434 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
9435 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009436 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009437 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009438 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009439 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
9440 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009441 { # pure virtual D2-destructors are marked as "virt" in the dump
9442 # virtual D2-destructors are NOT marked as "virt" in the dump
9443 # both destructors are not presented in the v-table
9444 next;
9445 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009446 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009447 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
9448 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009449 }
9450}
9451
9452sub registerOverriding($)
9453{
9454 my $LibVersion = $_[0];
9455 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009456 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009457 foreach my $ClassName (@Classes)
9458 {
9459 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
9460 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009461 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
9462 { # pure virtuals
9463 next;
9464 }
9465 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
9466 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009467 {
9468 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
9469 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
9470 { # both overridden virtual methods
9471 # and implemented pure virtual methods
9472 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
9473 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
9474 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
9475 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009476 }
9477 }
9478 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
9479 delete($VirtualTable{$LibVersion}{$ClassName});
9480 }
9481 }
9482}
9483
9484sub setVirtFuncPositions($)
9485{
9486 my $LibVersion = $_[0];
9487 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
9488 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009489 my ($Num, $Rel) = (1, 0);
9490
9491 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009492 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009493 if($UsedDump{$LibVersion}{"DWARF"}) {
9494 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
9495 }
9496 else {
9497 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
9498 }
9499 foreach my $VirtFunc (@Funcs)
9500 {
9501 if($UsedDump{$LibVersion}{"DWARF"}) {
9502 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
9503 }
9504 else {
9505 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
9506 }
9507
9508 # set relative positions
9509 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
9510 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
9511 { # relative position excluding added and removed virtual functions
9512 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
9513 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
9514 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
9515 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009516 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009517 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009518 }
9519 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009520 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009521 {
9522 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009523 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009524 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009525 }
9526 }
9527}
9528
9529sub get_sub_classes($$$)
9530{
9531 my ($ClassId, $LibVersion, $Recursive) = @_;
9532 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
9533 my @Subs = ();
9534 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
9535 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009536 if($Recursive)
9537 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009538 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
9539 push(@Subs, $SubSubId);
9540 }
9541 }
9542 push(@Subs, $SubId);
9543 }
9544 return @Subs;
9545}
9546
9547sub get_base_classes($$$)
9548{
9549 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009550 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009551 return () if(not defined $ClassType{"Base"});
9552 my @Bases = ();
9553 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
9554 keys(%{$ClassType{"Base"}}))
9555 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009556 if($Recursive)
9557 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009558 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
9559 push(@Bases, $SubBaseId);
9560 }
9561 }
9562 push(@Bases, $BaseId);
9563 }
9564 return @Bases;
9565}
9566
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009567sub getVTable_Model($$)
9568{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009569 my ($ClassId, $LibVersion) = @_;
9570 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
9571 my @Elements = ();
9572 foreach my $BaseId (@Bases, $ClassId)
9573 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009574 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009575 {
9576 if(defined $VirtualTable{$LibVersion}{$BName})
9577 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009578 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
9579 if($UsedDump{$LibVersion}{"DWARF"}) {
9580 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
9581 }
9582 else {
9583 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
9584 }
9585 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009586 push(@Elements, $VFunc);
9587 }
9588 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009589 }
9590 }
9591 return @Elements;
9592}
9593
9594sub getVShift($$)
9595{
9596 my ($ClassId, $LibVersion) = @_;
9597 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
9598 my $VShift = 0;
9599 foreach my $BaseId (@Bases)
9600 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009601 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009602 {
9603 if(defined $VirtualTable{$LibVersion}{$BName}) {
9604 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
9605 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009606 }
9607 }
9608 return $VShift;
9609}
9610
9611sub getShift($$)
9612{
9613 my ($ClassId, $LibVersion) = @_;
9614 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
9615 my $Shift = 0;
9616 foreach my $BaseId (@Bases)
9617 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009618 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009619 {
9620 if($Size!=1)
9621 { # not empty base class
9622 $Shift+=$Size;
9623 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009624 }
9625 }
9626 return $Shift;
9627}
9628
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009629sub getVTable_Size($$)
9630{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009631 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009632 my $Size = 0;
9633 # three approaches
9634 if(not $Size)
9635 { # real size
9636 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
9637 $Size = keys(%VTable);
9638 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009639 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009640 if(not $Size)
9641 { # shared library symbol size
9642 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
9643 $Size /= $WORD_SIZE{$LibVersion};
9644 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009645 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009646 if(not $Size)
9647 { # model size
9648 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
9649 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
9650 }
9651 }
9652 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009653}
9654
9655sub isCopyingClass($$)
9656{
9657 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009658 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009659}
9660
9661sub isLeafClass($$)
9662{
9663 my ($ClassId, $LibVersion) = @_;
9664 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
9665}
9666
9667sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009668{ # check structured type for public fields
9669 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009670}
9671
9672sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009673{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009674 my ($TypePtr, $Skip, $Start, $End) = @_;
9675 return 0 if(not $TypePtr);
9676 if($End==-1) {
9677 $End = keys(%{$TypePtr->{"Memb"}})-1;
9678 }
9679 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}}))
9680 {
9681 if($Skip and $Skip->{$MemPos})
9682 { # skip removed/added fields
9683 next;
9684 }
9685 if(int($MemPos)>=$Start and int($MemPos)<=$End)
9686 {
9687 if(isPublic($TypePtr, $MemPos)) {
9688 return ($MemPos+1);
9689 }
9690 }
9691 }
9692 return 0;
9693}
9694
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009695sub isReserved($)
9696{ # reserved fields == private
9697 my $MName = $_[0];
9698 if($MName=~/reserved|padding|f_spare/i) {
9699 return 1;
9700 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009701 if($MName=~/\A[_]*(spare|pad|unused)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009702 return 1;
9703 }
9704 if($MName=~/(pad\d+)/i) {
9705 return 1;
9706 }
9707 return 0;
9708}
9709
9710sub isPublic($$)
9711{
9712 my ($TypePtr, $FieldPos) = @_;
9713 return 0 if(not $TypePtr);
9714 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
9715 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
9716 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
9717 { # by name in C language
9718 # FIXME: add other methods to detect private members
9719 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
9720 if($MName=~/priv|abidata|parent_object/i)
9721 { # C-styled private data
9722 return 0;
9723 }
9724 if(lc($MName) eq "abi")
9725 { # ABI information/reserved field
9726 return 0;
9727 }
9728 if(isReserved($MName))
9729 { # reserved fields
9730 return 0;
9731 }
9732 return 1;
9733 }
9734 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
9735 { # by access in C++ language
9736 return 1;
9737 }
9738 return 0;
9739}
9740
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009741sub getVTable_Real($$)
9742{
9743 my ($ClassName, $LibVersion) = @_;
9744 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9745 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009746 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009747 if(defined $Type{"VTable"}) {
9748 return %{$Type{"VTable"}};
9749 }
9750 }
9751 return ();
9752}
9753
9754sub cmpVTables($)
9755{
9756 my $ClassName = $_[0];
9757 my $Res = cmpVTables_Real($ClassName, 1);
9758 if($Res==-1) {
9759 $Res = cmpVTables_Model($ClassName);
9760 }
9761 return $Res;
9762}
9763
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009764sub cmpVTables_Model($)
9765{
9766 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009767 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009768 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009769 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009770 return 1;
9771 }
9772 }
9773 return 0;
9774}
9775
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009776sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009777{
9778 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009779 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
9780 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009781 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009782 my %VTable_Old = getVTable_Real($ClassName, 1);
9783 my %VTable_New = getVTable_Real($ClassName, 2);
9784 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009785 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009786 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009787 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009788 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009789 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
9790 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009791 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009792 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009793 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009794 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009795 my $Entry1 = $VTable_Old{$Offset};
9796 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009797 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009798 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009799 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009800 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009801 $Entry1 = simpleVEntry($Entry1);
9802 $Entry2 = simpleVEntry($Entry2);
9803 if($Entry1 ne $Entry2)
9804 { # register as changed
9805 if($Entry1=~/::([^:]+)\Z/)
9806 {
9807 my $M1 = $1;
9808 if($Entry2=~/::([^:]+)\Z/)
9809 {
9810 my $M2 = $1;
9811 if($M1 eq $M2)
9812 { # overridden
9813 next;
9814 }
9815 }
9816 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009817 if(differentDumps("G"))
9818 {
9819 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
9820 {
9821 # GCC 4.6.1: -0x00000000000000010
9822 # GCC 4.7.0: -16
9823 next;
9824 }
9825 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009826 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009827 }
9828 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009829 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009830}
9831
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009832sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009833{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009834 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009835 foreach my $ClassName (keys(%{$VirtualTable{1}}))
9836 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009837 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009838 { # already registered
9839 next;
9840 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009841 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009842 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009843 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009844 foreach my $Symbol (@Affected)
9845 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009846 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009847 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009848 "Target"=>$ClassName);
9849 }
9850 }
9851 }
9852}
9853
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009854sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009855{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009856 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009857 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009858 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009859 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009860 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009861 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009862 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009863 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009864 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009865 if($TName_Tid{1}{$ClassName}
9866 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009867 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009868 if(defined $CompleteSignature{1}{$Symbol}
9869 and $CompleteSignature{1}{$Symbol}{"Virt"})
9870 { # override some method in v.1
9871 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009872 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009873 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009874 }
9875 }
9876 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009877 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009878 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009879 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009880 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009881 if($TName_Tid{2}{$ClassName}
9882 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009883 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009884 if(defined $CompleteSignature{2}{$Symbol}
9885 and $CompleteSignature{2}{$Symbol}{"Virt"})
9886 { # override some method in v.2
9887 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009888 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009889 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009890 }
9891 }
9892 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009893 if($Level eq "Binary")
9894 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009895 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009896 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
9897 { # check replacements, including pure virtual methods
9898 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
9899 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009900 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009901 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
9902 if($AddedPos==$RemovedPos)
9903 {
9904 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
9905 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
9906 last; # other methods will be reported as "added" or "removed"
9907 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009908 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009909 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
9910 {
9911 if(lc($AddedVFunc) eq lc($RemovedVFunc))
9912 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009913 next;
9914 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009915 my $ProblemType = "Virtual_Replacement";
9916 my @Affected = ($RemovedVFunc);
9917 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
9918 { # pure methods
9919 if(not isUsedClass($ClassId, 1, $Level))
9920 { # not a parameter of some exported method
9921 next;
9922 }
9923 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009924
9925 # affected all methods (both virtual and non-virtual ones)
9926 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
9927 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009928 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009929 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009930 foreach my $AffectedInt (@Affected)
9931 {
9932 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
9933 { # affected exported methods only
9934 next;
9935 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009936 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
9937 next;
9938 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009939 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
9940 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009941 "Target"=>get_Signature($AddedVFunc, 2),
9942 "Old_Value"=>get_Signature($RemovedVFunc, 1));
9943 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009944 }
9945 }
9946 }
9947 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009948 if(not checkDump(1, "2.0")
9949 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009950 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009951 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009952 return;
9953 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009954 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009955 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009956 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009957 next if(not $ClassId_Old);
9958 if(not isCreatable($ClassId_Old, 1))
9959 { # skip classes without public constructors (including auto-generated)
9960 # example: class has only a private exported or private inline constructor
9961 next;
9962 }
9963 if($ClassName=~/>/)
9964 { # skip affected template instances
9965 next;
9966 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009967 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009968 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009969 if(not $ClassId_New) {
9970 next;
9971 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009972 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009973 if($Class_New{"Type"}!~/Class|Struct/)
9974 { # became typedef
9975 if($Level eq "Binary") {
9976 next;
9977 }
9978 if($Level eq "Source")
9979 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009980 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009981 if($Class_New{"Type"}!~/Class|Struct/) {
9982 next;
9983 }
9984 $ClassId_New = $Class_New{"Tid"};
9985 }
9986 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009987 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
9988 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 +04009989
9990 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
9991 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
9992
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009993 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009994 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
9995 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009996 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
9997 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009998 my $Shift_Old = getShift($ClassId_Old, 1);
9999 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010000 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010001 my ($Added, $Removed) = (0, 0);
10002 my @StableBases_Old = ();
10003 foreach my $BaseId (@Bases_Old)
10004 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010005 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010006 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010007 push(@StableBases_Old, $BaseId);
10008 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010009 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010010 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010011 { # removed base
10012 # excluding namespace::SomeClass to SomeClass renaming
10013 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010014 if($Level eq "Binary")
10015 { # Binary-level
10016 if($Shift_Old ne $Shift_New)
10017 { # affected fields
10018 if(havePubFields(\%Class_Old)) {
10019 $ProblemKind .= "_And_Shift";
10020 }
10021 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10022 $ProblemKind .= "_And_Size";
10023 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010024 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010025 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10026 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010027 { # affected v-table
10028 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010029 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010030 }
10031 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010032 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010033 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10034 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010035 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10036 {
10037 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10038 if($ProblemKind=~/VTable/) {
10039 $VTableChanged_M{$SubName}=1;
10040 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010041 }
10042 }
10043 foreach my $Interface (@Affected)
10044 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010045 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10046 next;
10047 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010048 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010049 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010050 "Target"=>$BaseName,
10051 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10052 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10053 "Shift"=>abs($Shift_New-$Shift_Old) );
10054 }
10055 $Removed+=1;
10056 }
10057 }
10058 my @StableBases_New = ();
10059 foreach my $BaseId (@Bases_New)
10060 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010061 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010062 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010063 push(@StableBases_New, $BaseId);
10064 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010065 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010066 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010067 { # added base
10068 # excluding namespace::SomeClass to SomeClass renaming
10069 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010070 if($Level eq "Binary")
10071 { # Binary-level
10072 if($Shift_Old ne $Shift_New)
10073 { # affected fields
10074 if(havePubFields(\%Class_Old)) {
10075 $ProblemKind .= "_And_Shift";
10076 }
10077 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10078 $ProblemKind .= "_And_Size";
10079 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010080 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010081 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10082 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010083 { # affected v-table
10084 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010085 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010086 }
10087 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010088 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010089 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10090 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010091 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10092 {
10093 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10094 if($ProblemKind=~/VTable/) {
10095 $VTableChanged_M{$SubName}=1;
10096 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010097 }
10098 }
10099 foreach my $Interface (@Affected)
10100 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010101 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10102 next;
10103 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010104 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010105 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010106 "Target"=>$BaseName,
10107 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10108 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10109 "Shift"=>abs($Shift_New-$Shift_Old) );
10110 }
10111 $Added+=1;
10112 }
10113 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010114 if($Level eq "Binary")
10115 { # Binary-level
10116 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010117 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10118 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010119 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010120 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010121 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010122 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010123 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010124 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10125 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010126 if($NewPos!=$OldPos)
10127 { # changed position of the base class
10128 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010129 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010130 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10131 next;
10132 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010133 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10134 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010135 "Target"=>$BaseName,
10136 "Old_Value"=>$OldPos-1,
10137 "New_Value"=>$NewPos-1 );
10138 }
10139 }
10140 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10141 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10142 { # became non-virtual base
10143 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10144 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010145 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10146 next;
10147 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010148 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10149 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010150 "Target"=>$BaseName );
10151 }
10152 }
10153 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10154 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10155 { # became virtual base
10156 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10157 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010158 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10159 next;
10160 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010161 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10162 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010163 "Target"=>$BaseName );
10164 }
10165 }
10166 }
10167 }
10168 # detect size changes in base classes
10169 if($Shift_Old!=$Shift_New)
10170 { # size of allocable class
10171 foreach my $BaseId (@StableBases_Old)
10172 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010173 my %BaseType = get_Type($BaseId, 1);
10174 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010175 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010176 if($Size_Old ne $Size_New
10177 and $Size_Old and $Size_New)
10178 {
10179 my $ProblemType = "";
10180 if(isCopyingClass($BaseId, 1)) {
10181 $ProblemType = "Size_Of_Copying_Class";
10182 }
10183 elsif($AllocableClass{1}{$BaseType{"Name"}})
10184 {
10185 if($Size_New>$Size_Old)
10186 { # increased size
10187 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010188 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010189 else
10190 { # decreased size
10191 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10192 if(not havePubFields(\%Class_Old))
10193 { # affected class has no public members
10194 next;
10195 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010196 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010197 }
10198 next if(not $ProblemType);
10199 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10200 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010201 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10202 next;
10203 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010204 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10205 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010206 "Target"=>$BaseType{"Name"},
10207 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10208 "New_Size"=>$Size_New*$BYTE_SIZE );
10209 }
10210 }
10211 }
10212 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010213 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010214 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010215 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010216 { # compare virtual tables size in base classes
10217 my $VShift_Old = getVShift($ClassId_Old, 1);
10218 my $VShift_New = getVShift($ClassId_New, 2);
10219 if($VShift_Old ne $VShift_New)
10220 { # changes in the base class or changes in the list of base classes
10221 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10222 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10223 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010224 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010225 foreach my $BaseId (@AllBases_Old)
10226 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010227 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010228 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010229 { # lost base
10230 next;
10231 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010232 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10233 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010234 if($VSize_Old!=$VSize_New)
10235 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010236 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010237 { # TODO: affected non-virtual methods?
10238 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010239 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10240 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010241 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010242 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010243 { # skip interfaces that have not changed the absolute virtual position
10244 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010245 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010246 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10247 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010248 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010249 $VTableChanged_M{$BaseType{"Name"}} = 1;
10250 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010251 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10252 { # the reason of the layout change: added virtual functions
10253 next if($VirtualReplacement{$VirtFunc});
10254 my $ProblemType = "Added_Virtual_Method";
10255 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10256 $ProblemType = "Added_Pure_Virtual_Method";
10257 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010258 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010259 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010260 "Target"=>get_Signature($VirtFunc, 2) );
10261 }
10262 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
10263 { # the reason of the layout change: removed virtual functions
10264 next if($VirtualReplacement{$VirtFunc});
10265 my $ProblemType = "Removed_Virtual_Method";
10266 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
10267 $ProblemType = "Removed_Pure_Virtual_Method";
10268 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010269 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010270 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010271 "Target"=>get_Signature($VirtFunc, 1) );
10272 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010273 }
10274 }
10275 }
10276 }
10277 }
10278 }
10279 }
10280}
10281
10282sub isCreatable($$)
10283{
10284 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010285 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010286 or isCopyingClass($ClassId, $LibVersion)) {
10287 return 1;
10288 }
10289 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10290 { # Fix for incomplete data: if this class has
10291 # a base class then it should also has a constructor
10292 return 1;
10293 }
10294 if($ReturnedClass{$LibVersion}{$ClassId})
10295 { # returned by some method of this class
10296 # or any other class
10297 return 1;
10298 }
10299 return 0;
10300}
10301
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010302sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010303{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010304 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010305 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
10306 { # parameter of some exported method
10307 return 1;
10308 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010309 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
10310 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010311 { # method from target class
10312 return 1;
10313 }
10314 return 0;
10315}
10316
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010317sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010318{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010319 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010320 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010321 # - virtual
10322 # - pure-virtual
10323 # - non-virtual
10324 if($CompleteSignature{1}{$Interface}{"Data"})
10325 { # global data is not affected
10326 return;
10327 }
10328 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010329 if(not $Class_Id) {
10330 return;
10331 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010332 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010333 if(cmpVTables_Real($CName, 1)==0)
10334 { # no changes
10335 return;
10336 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010337 $CheckedTypes{$Level}{$CName} = 1;
10338 if($Level eq "Binary")
10339 { # Binary-level
10340 if($CompleteSignature{1}{$Interface}{"PureVirt"}
10341 and not isUsedClass($Class_Id, 1, $Level))
10342 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010343 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010344 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010345 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010346 }
10347 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
10348 {
10349 if(defined $VirtualTable{2}{$CName}{$Func}
10350 and defined $CompleteSignature{2}{$Func})
10351 {
10352 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
10353 and $CompleteSignature{2}{$Func}{"PureVirt"})
10354 { # became pure virtual
10355 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
10356 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010357 "Target"=>get_Signature_M($Func, 1) );
10358 $VTableChanged_M{$CName} = 1;
10359 }
10360 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
10361 and not $CompleteSignature{2}{$Func}{"PureVirt"})
10362 { # became non-pure virtual
10363 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
10364 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010365 "Target"=>get_Signature_M($Func, 1) );
10366 $VTableChanged_M{$CName} = 1;
10367 }
10368 }
10369 }
10370 if($Level eq "Binary")
10371 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010372 # check virtual table structure
10373 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
10374 {
10375 next if($Interface eq $AddedVFunc);
10376 next if($VirtualReplacement{$AddedVFunc});
10377 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
10378 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
10379 { # pure virtual methods affect all others (virtual and non-virtual)
10380 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010381 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010382 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010383 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010384 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010385 elsif(not defined $VirtualTable{1}{$CName}
10386 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010387 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010388 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010389 { # became polymorphous class, added v-table pointer
10390 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010391 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010392 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010393 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010394 }
10395 else
10396 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010397 my $VSize_Old = getVTable_Size($CName, 1);
10398 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010399 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010400 if(isCopyingClass($Class_Id, 1))
10401 { # class has no constructors and v-table will be copied by applications, this may affect all methods
10402 my $ProblemType = "Added_Virtual_Method";
10403 if(isLeafClass($Class_Id, 1)) {
10404 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
10405 }
10406 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10407 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010408 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010409 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010410 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010411 else
10412 {
10413 my $ProblemType = "Added_Virtual_Method";
10414 if(isLeafClass($Class_Id, 1)) {
10415 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
10416 }
10417 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10418 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010419 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010420 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010421 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010422 }
10423 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010424 elsif($CompleteSignature{1}{$Interface}{"Virt"}
10425 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010426 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010427 if(defined $VirtualTable{1}{$CName}
10428 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010429 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010430 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
10431 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010432
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010433 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010434 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010435 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
10436 foreach my $ASymbol (@Affected)
10437 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010438 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
10439 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010440 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010441 next;
10442 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010443 }
10444 $CheckedSymbols{$Level}{$ASymbol} = 1;
10445 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
10446 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010447 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010448 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010449 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010450 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010451 }
10452 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010453 else {
10454 # safe
10455 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010456 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010457 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
10458 {
10459 next if($VirtualReplacement{$RemovedVFunc});
10460 if($RemovedVFunc eq $Interface
10461 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10462 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010463 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010464 next;
10465 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010466 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010467 { # became non-polymorphous class, removed v-table pointer
10468 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
10469 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010470 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010471 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010472 }
10473 elsif($CompleteSignature{1}{$Interface}{"Virt"}
10474 or $CompleteSignature{1}{$Interface}{"PureVirt"})
10475 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010476 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010477 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010478 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
10479 next;
10480 }
10481 my $VPos_New = -1;
10482 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010483 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010484 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
10485 }
10486 else
10487 {
10488 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010489 next;
10490 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010491 }
10492 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
10493 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
10494 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
10495 {
10496 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
10497 foreach my $ASymbol (@Affected)
10498 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010499 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
10500 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010501 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010502 next;
10503 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010504 }
10505 my $ProblemType = "Removed_Virtual_Method";
10506 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
10507 $ProblemType = "Removed_Pure_Virtual_Method";
10508 }
10509 $CheckedSymbols{$Level}{$ASymbol} = 1;
10510 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
10511 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010512 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010513 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010514 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010515 }
10516 }
10517 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010518 }
10519 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010520 else
10521 { # Source-level
10522 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010523 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010524 next if($Interface eq $AddedVFunc);
10525 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010526 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010527 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
10528 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010529 "Target"=>get_Signature($AddedVFunc, 2) );
10530 }
10531 }
10532 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
10533 {
10534 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10535 {
10536 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
10537 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010538 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010539 }
10540 }
10541 }
10542}
10543
10544sub find_MemberPair_Pos_byName($$)
10545{
10546 my ($Member_Name, $Pair_Type) = @_;
10547 $Member_Name=~s/\A[_]+|[_]+\Z//g;
10548 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
10549 {
10550 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
10551 {
10552 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
10553 $Name=~s/\A[_]+|[_]+\Z//g;
10554 if($Name eq $Member_Name) {
10555 return $MemberPair_Pos;
10556 }
10557 }
10558 }
10559 return "lost";
10560}
10561
10562sub find_MemberPair_Pos_byVal($$)
10563{
10564 my ($Member_Value, $Pair_Type) = @_;
10565 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
10566 {
10567 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
10568 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
10569 return $MemberPair_Pos;
10570 }
10571 }
10572 return "lost";
10573}
10574
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010575my %Severity_Val=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010576 "High"=>3,
10577 "Medium"=>2,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010578 "Low"=>1,
10579 "Safe"=>-1
10580);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010581
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010582sub maxSeverity($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010583{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010584 my ($S1, $S2) = @_;
10585 if(cmpSeverities($S1, $S2)) {
10586 return $S1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010587 }
10588 else {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010589 return $S2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010590 }
10591}
10592
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010593sub cmpSeverities($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010594{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010595 my ($S1, $S2) = @_;
10596 if(not $S1) {
10597 return 0;
10598 }
10599 elsif(not $S2) {
10600 return 1;
10601 }
10602 return ($Severity_Val{$S1}>$Severity_Val{$S2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010603}
10604
10605sub getProblemSeverity($$)
10606{
10607 my ($Level, $Kind) = @_;
10608 return $CompatRules{$Level}{$Kind}{"Severity"};
10609}
10610
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010611sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010612{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010613 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010614 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010615 if( $_->{"T1"} eq $_[0]
10616 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010617 {
10618 return 1;
10619 }
10620 }
10621 return 0;
10622}
10623
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010624sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010625{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010626 my %IDs = (
10627 "T1" => $_[0],
10628 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010629 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010630 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010631}
10632
10633sub isRenamed($$$$$)
10634{
10635 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
10636 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
10637 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010638 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010639 if(not defined $Type2->{"Memb"}{$MemPos}) {
10640 return "";
10641 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010642 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010643 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010644
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010645 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
10646 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010647 if($MemberPair_Pos_Rev eq "lost")
10648 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010649 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
10650 { # base type match
10651 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010652 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010653 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
10654 { # exact type match
10655 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010656 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010657 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
10658 { # size match
10659 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010660 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010661 if(isReserved($Pair_Name))
10662 { # reserved fields
10663 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010664 }
10665 }
10666 return "";
10667}
10668
10669sub isLastElem($$)
10670{
10671 my ($Pos, $TypeRef) = @_;
10672 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
10673 if($Name=~/last|count|max|total/i)
10674 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
10675 return 1;
10676 }
10677 elsif($Name=~/END|NLIMITS\Z/)
10678 { # __RLIMIT_NLIMITS
10679 return 1;
10680 }
10681 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
10682 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
10683 { # NImageFormats, NColorRoles
10684 return 1;
10685 }
10686 return 0;
10687}
10688
10689sub nonComparable($$)
10690{
10691 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010692
10693 my $N1 = $T1->{"Name"};
10694 my $N2 = $T2->{"Name"};
10695
10696 $N1=~s/\A(struct|union|enum) //;
10697 $N2=~s/\A(struct|union|enum) //;
10698
10699 if($N1 ne $N2
10700 and not isAnon($N1)
10701 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010702 { # different names
10703 if($T1->{"Type"} ne "Pointer"
10704 or $T2->{"Type"} ne "Pointer")
10705 { # compare base types
10706 return 1;
10707 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010708 if($N1!~/\Avoid\s*\*/
10709 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010710 {
10711 return 1;
10712 }
10713 }
10714 elsif($T1->{"Type"} ne $T2->{"Type"})
10715 { # different types
10716 if($T1->{"Type"} eq "Class"
10717 and $T2->{"Type"} eq "Struct")
10718 { # "class" to "struct"
10719 return 0;
10720 }
10721 elsif($T2->{"Type"} eq "Class"
10722 and $T1->{"Type"} eq "Struct")
10723 { # "struct" to "class"
10724 return 0;
10725 }
10726 else
10727 { # "class" to "enum"
10728 # "union" to "class"
10729 # ...
10730 return 1;
10731 }
10732 }
10733 return 0;
10734}
10735
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010736sub isOpaque($)
10737{
10738 my $T = $_[0];
10739 if(not defined $T->{"Memb"})
10740 {
10741 return 1;
10742 }
10743 return 0;
10744}
10745
10746sub removeVPtr($)
10747{ # support for old ABI dumps
10748 my $TPtr = $_[0];
10749 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
10750 if($#Pos>=1)
10751 {
10752 foreach my $Pos (0 .. $#Pos-1)
10753 {
10754 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
10755 }
10756 delete($TPtr->{"Memb"}{$#Pos});
10757 }
10758}
10759
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010760sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010761{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010762 my ($Type1_Id, $Type2_Id, $Level) = @_;
10763 return () if(not $Type1_Id or not $Type2_Id);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010764 my (%Sub_SubProblems, %SubProblems) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010765 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010766 { # already merged
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010767 return %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010768 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010769 my %Type1 = get_Type($Type1_Id, 1);
10770 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010771 if(not $Type1{"Name"} or not $Type2{"Name"}) {
10772 return ();
10773 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010774
10775 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010776 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
10777 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010778 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
10779
10780 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
10781 {
10782 if($Type1_Pure{"Type"}=~/Struct|Union/
10783 and $Type2_Pure{"Type"}=~/Struct|Union/)
10784 {
10785 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
10786 {
10787 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
10788 "Target"=>$Type1_Pure{"Name"},
10789 "Type_Name"=>$Type1_Pure{"Name"} );
10790
10791 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
10792 return %SubProblems;
10793 }
10794 }
10795 }
10796
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010797 if(not $Type1_Pure{"Size"} or not $Type2_Pure{"Size"})
10798 { # including a case when "class Class { ... };" changed to "class Class;"
10799 return ();
10800 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010801 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010802 { # skip recursive declarations
10803 return ();
10804 }
10805 return () if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
10806 return () if($SkipTypes{1}{$Type1_Pure{"Name"}});
10807 return () if($SkipTypes{1}{$Type1{"Name"}});
10808
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010809 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
10810 { # support for old ABI dumps
10811 # _vptr field added in 3.0
10812 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
10813 {
10814 if(defined $Type2_Pure{"Memb"}
10815 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
10816 {
10817 if(keys(%{$Type2_Pure{"Memb"}})==1) {
10818 delete($Type2_Pure{"Memb"}{0});
10819 }
10820 else {
10821 removeVPtr(\%Type2_Pure);
10822 }
10823 }
10824 }
10825 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
10826 {
10827 if(defined $Type1_Pure{"Memb"}
10828 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
10829 {
10830 if(keys(%{$Type1_Pure{"Memb"}})==1) {
10831 delete($Type1_Pure{"Memb"}{0});
10832 }
10833 else {
10834 removeVPtr(\%Type1_Pure);
10835 }
10836 }
10837 }
10838 }
10839
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010840 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
10841 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010842
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010843 if(not $UseOldDumps and %Typedef_1 and %Typedef_2
10844 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
10845 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010846 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010847 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
10848 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010849 if($Base_1{"Name"} ne $Base_2{"Name"})
10850 {
10851 if(differentDumps("G")
10852 or differentDumps("V"))
10853 { # different GCC versions or different dumps
10854 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
10855 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
10856 # std::__va_list and __va_list
10857 $Base_1{"Name"}=~s/\A(\w+::)+//;
10858 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010859 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
10860 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010861 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010862 }
10863 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
10864 and $Base_1{"Name"} ne $Base_2{"Name"})
10865 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010866 if($Level eq "Binary"
10867 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010868 {
10869 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
10870 "Target"=>$Typedef_1{"Name"},
10871 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010872 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
10873 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
10874 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010875 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
10876 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010877 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010878 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010879 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
10880 {
10881 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
10882 "Target"=>$Typedef_1{"Name"},
10883 "Type_Name"=>$Typedef_1{"Name"},
10884 "Old_Value"=>$Base_1{"Name"},
10885 "New_Value"=>$Base_2{"Name"} );
10886 }
10887 else
10888 {
10889 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
10890 "Target"=>$Typedef_1{"Name"},
10891 "Type_Name"=>$Typedef_1{"Name"},
10892 "Old_Value"=>$Base_1{"Name"},
10893 "New_Value"=>$Base_2{"Name"} );
10894 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010895 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010896 }
10897 }
10898 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
10899 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010900 my $TT1 = $Type1_Pure{"Type"};
10901 my $TT2 = $Type2_Pure{"Type"};
10902
10903 if($TT1 ne $TT2
10904 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010905 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010906 my $Short1 = $Type1_Pure{"Name"};
10907 my $Short2 = $Type2_Pure{"Name"};
10908
10909 $Short1=~s/\A\Q$TT1\E //ig;
10910 $Short2=~s/\A\Q$TT2\E //ig;
10911
10912 if($Short1 eq $Short2)
10913 {
10914 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
10915 "Target"=>$Type1_Pure{"Name"},
10916 "Type_Name"=>$Type1_Pure{"Name"},
10917 "Old_Value"=>lc($Type1_Pure{"Type"}),
10918 "New_Value"=>lc($Type2_Pure{"Type"}) );
10919 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010920 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010921 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010922 return %SubProblems;
10923 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010924 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010925 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
10926 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
10927 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
10928 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010929 if($Level eq "Binary"
10930 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010931 {
10932 my $ProblemKind = "DataType_Size";
10933 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010934 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010935 {
10936 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
10937 $ProblemKind = "Size_Of_Copying_Class";
10938 }
10939 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
10940 {
10941 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
10942 $ProblemKind = "Size_Of_Allocable_Class_Increased";
10943 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010944 else
10945 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010946 # descreased size of allocable class
10947 # it has no special effects
10948 }
10949 }
10950 }
10951 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
10952 "Target"=>$Type1_Pure{"Name"},
10953 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010954 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
10955 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE,
10956 "InitialType_Type"=>$Type1_Pure{"Type"} );
10957 }
10958 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010959 if(defined $Type1_Pure{"BaseType"}
10960 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010961 { # checking base types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010962 %Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010963 foreach my $Sub_SubProblemType (keys(%Sub_SubProblems))
10964 {
10965 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems{$Sub_SubProblemType}}))
10966 {
10967 foreach my $Attr (keys(%{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}})) {
10968 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr} = $Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr};
10969 }
10970 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{"InitialType_Type"} = $Type1_Pure{"Type"};
10971 }
10972 }
10973 }
10974 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
10975 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
10976 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
10977 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
10978 { # detect removed and renamed fields
10979 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
10980 next if(not $Member_Name);
10981 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);
10982 if($MemberPair_Pos eq "lost")
10983 {
10984 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
10985 {
10986 if(isUnnamed($Member_Name))
10987 { # support for old-version dumps
10988 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010989 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010990 next;
10991 }
10992 }
10993 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
10994 { # renamed
10995 $RenamedField{$Member_Pos}=$RenamedTo;
10996 $RenamedField_Rev{$NameToPosB{$RenamedTo}}=$Member_Name;
10997 }
10998 else
10999 { # removed
11000 $RemovedField{$Member_Pos}=1;
11001 }
11002 }
11003 elsif($Type1_Pure{"Type"} eq "Enum")
11004 {
11005 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11006 next if($Member_Value1 eq "");
11007 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11008 if($MemberPair_Pos ne "lost")
11009 { # renamed
11010 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11011 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11012 if($MemberPair_Pos_Rev eq "lost")
11013 {
11014 $RenamedField{$Member_Pos}=$RenamedTo;
11015 $RenamedField_Rev{$NameToPosB{$RenamedTo}}=$Member_Name;
11016 }
11017 else {
11018 $RemovedField{$Member_Pos}=1;
11019 }
11020 }
11021 else
11022 { # removed
11023 $RemovedField{$Member_Pos}=1;
11024 }
11025 }
11026 }
11027 else
11028 { # related
11029 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11030 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11031 }
11032 }
11033 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11034 { # detect added fields
11035 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11036 next if(not $Member_Name);
11037 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);
11038 if($MemberPair_Pos eq "lost")
11039 {
11040 if(isUnnamed($Member_Name))
11041 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011042 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011043 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011044 next;
11045 }
11046 }
11047 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11048 {
11049 if(not $RenamedField_Rev{$Member_Pos})
11050 { # added
11051 $AddedField{$Member_Pos}=1;
11052 }
11053 }
11054 }
11055 }
11056 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11057 { # detect moved fields
11058 my (%RelPos, %RelPosName, %AbsPos) = ();
11059 my $Pos = 0;
11060 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11061 { # relative positions in 1st version
11062 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11063 next if(not $Member_Name);
11064 if(not $RemovedField{$Member_Pos})
11065 { # old type without removed fields
11066 $RelPos{1}{$Member_Name}=$Pos;
11067 $RelPosName{1}{$Pos} = $Member_Name;
11068 $AbsPos{1}{$Pos++} = $Member_Pos;
11069 }
11070 }
11071 $Pos = 0;
11072 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11073 { # relative positions in 2nd version
11074 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11075 next if(not $Member_Name);
11076 if(not $AddedField{$Member_Pos})
11077 { # new type without added fields
11078 $RelPos{2}{$Member_Name}=$Pos;
11079 $RelPosName{2}{$Pos} = $Member_Name;
11080 $AbsPos{2}{$Pos++} = $Member_Pos;
11081 }
11082 }
11083 foreach my $Member_Name (keys(%{$RelPos{1}}))
11084 {
11085 my $RPos1 = $RelPos{1}{$Member_Name};
11086 my $AbsPos1 = $NameToPosA{$Member_Name};
11087 my $Member_Name2 = $Member_Name;
11088 if(my $RenamedTo = $RenamedField{$AbsPos1})
11089 { # renamed
11090 $Member_Name2 = $RenamedTo;
11091 }
11092 my $RPos2 = $RelPos{2}{$Member_Name2};
11093 if($RPos2 ne "" and $RPos1 ne $RPos2)
11094 { # different relative positions
11095 my $AbsPos2 = $NameToPosB{$Member_Name2};
11096 if($AbsPos1 ne $AbsPos2)
11097 { # different absolute positions
11098 my $ProblemType = "Moved_Field";
11099 if(not isPublic(\%Type1_Pure, $AbsPos1))
11100 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011101 if($Level eq "Source") {
11102 next;
11103 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011104 $ProblemType = "Moved_Private_Field";
11105 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011106 if($Level eq "Binary"
11107 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011108 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011109 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011110 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011111 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011112 if($MemSize1 ne $MemSize2) {
11113 $ProblemType .= "_And_Size";
11114 }
11115 }
11116 if($ProblemType eq "Moved_Private_Field") {
11117 next;
11118 }
11119 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11120 "Target"=>$Member_Name,
11121 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011122 "Old_Value"=>$RPos1,
11123 "New_Value"=>$RPos2 );
11124 }
11125 }
11126 }
11127 }
11128 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011129 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011130 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11131 next if(not $Member_Name);
11132 if(my $RenamedTo = $RenamedField{$Member_Pos})
11133 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011134 if(defined $Constants{2}{$Member_Name})
11135 {
11136 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11137 { # define OLD NEW
11138 next; # Safe
11139 }
11140 }
11141
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011142 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11143 {
11144 if(isPublic(\%Type1_Pure, $Member_Pos))
11145 {
11146 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11147 "Target"=>$Member_Name,
11148 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011149 "Old_Value"=>$Member_Name,
11150 "New_Value"=>$RenamedTo );
11151 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011152 elsif(isReserved($Member_Name))
11153 {
11154 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11155 "Target"=>$Member_Name,
11156 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011157 "Old_Value"=>$Member_Name,
11158 "New_Value"=>$RenamedTo );
11159 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011160 }
11161 elsif($Type1_Pure{"Type"} eq "Enum")
11162 {
11163 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11164 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11165 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011166 "Old_Value"=>$Member_Name,
11167 "New_Value"=>$RenamedTo );
11168 }
11169 }
11170 elsif($RemovedField{$Member_Pos})
11171 { # removed
11172 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11173 {
11174 my $ProblemType = "Removed_Field";
11175 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011176 or isUnnamed($Member_Name))
11177 {
11178 if($Level eq "Source") {
11179 next;
11180 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011181 $ProblemType = "Removed_Private_Field";
11182 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011183 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011184 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011185 {
11186 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11187 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011188 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 +040011189 { # changed offset
11190 $ProblemType .= "_And_Layout";
11191 }
11192 }
11193 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11194 { # affected size
11195 $ProblemType .= "_And_Size";
11196 }
11197 }
11198 if($ProblemType eq "Removed_Private_Field") {
11199 next;
11200 }
11201 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11202 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011203 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011204 }
11205 elsif($Type2_Pure{"Type"} eq "Union")
11206 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011207 if($Level eq "Binary"
11208 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011209 {
11210 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11211 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011212 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011213 }
11214 else
11215 {
11216 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11217 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011218 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011219 }
11220 }
11221 elsif($Type1_Pure{"Type"} eq "Enum")
11222 {
11223 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11224 "Target"=>$Member_Name,
11225 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011226 "Old_Value"=>$Member_Name );
11227 }
11228 }
11229 else
11230 { # changed
11231 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11232 if($Type1_Pure{"Type"} eq "Enum")
11233 {
11234 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11235 next if($Member_Value1 eq "");
11236 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11237 next if($Member_Value2 eq "");
11238 if($Member_Value1 ne $Member_Value2)
11239 {
11240 my $ProblemType = "Enum_Member_Value";
11241 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11242 $ProblemType = "Enum_Last_Member_Value";
11243 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011244 if($SkipConstants{1}{$Member_Name}) {
11245 $ProblemType = "Enum_Private_Member_Value";
11246 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011247 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11248 "Target"=>$Member_Name,
11249 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011250 "Old_Value"=>$Member_Value1,
11251 "New_Value"=>$Member_Value2 );
11252 }
11253 }
11254 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11255 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011256 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
11257 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
11258
11259 if($Access1 ne "private"
11260 and $Access2 eq "private")
11261 {
11262 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
11263 "Target"=>$Member_Name,
11264 "Type_Name"=>$Type1_Pure{"Name"});
11265 }
11266 elsif($Access1 ne "protected"
11267 and $Access1 ne "private"
11268 and $Access2 eq "protected")
11269 {
11270 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
11271 "Target"=>$Member_Name,
11272 "Type_Name"=>$Type1_Pure{"Name"});
11273 }
11274
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011275 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
11276 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011277 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011278 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
11279 $SizeV1 = $BSize1;
11280 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011281 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011282 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
11283 $SizeV2 = $BSize2;
11284 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011285 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
11286 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011287 if($Level eq "Binary"
11288 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011289 {
11290 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
11291 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
11292 { # field size change (including anon-structures and unions)
11293 # - same types
11294 # - unnamed types
11295 # - bitfields
11296 my $ProblemType = "Field_Size";
11297 if(not isPublic(\%Type1_Pure, $Member_Pos)
11298 or isUnnamed($Member_Name))
11299 { # should not be accessed by applications, goes to "Low Severity"
11300 # example: "abidata" members in GStreamer types
11301 $ProblemType = "Private_".$ProblemType;
11302 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011303 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 +040011304 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011305 if($Type2_Pure{"Type"} ne "Union"
11306 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011307 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011308 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 +040011309 { # changed offset
11310 $ProblemType .= "_And_Layout";
11311 }
11312 }
11313 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11314 $ProblemType .= "_And_Type_Size";
11315 }
11316 }
11317 if($ProblemType eq "Private_Field_Size")
11318 { # private field size with no effect
11319 $ProblemType = "";
11320 }
11321 if($ProblemType)
11322 { # register a problem
11323 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11324 "Target"=>$Member_Name,
11325 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011326 "Old_Size"=>$SizeV1,
11327 "New_Size"=>$SizeV2);
11328 }
11329 }
11330 }
11331 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
11332 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
11333 { # do NOT check bitfield type changes
11334 next;
11335 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011336 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011337 {
11338 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
11339 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
11340 {
11341 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
11342 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011343 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011344 }
11345 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
11346 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
11347 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011348 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011349 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011350 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011351 }
11352 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011353 %Sub_SubProblems = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011354 foreach my $ProblemType (keys(%Sub_SubProblems))
11355 {
11356 my $Old_Value = $Sub_SubProblems{$ProblemType}{"Old_Value"};
11357 my $New_Value = $Sub_SubProblems{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011358
11359 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011360 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011361 or $ProblemType eq "Field_Type_And_Size"
11362 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011363 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011364 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011365 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011366 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011367 %{$Sub_SubProblems{"Field_Became_Volatile"}} = %{$Sub_SubProblems{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011368 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011369 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
11370 %{$Sub_SubProblems{"Field_Became_Non_Volatile"}} = %{$Sub_SubProblems{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011371 }
11372 }
11373 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
11374 {
11375 if($RA==2) {
11376 %{$Sub_SubProblems{"Field_Added_Const"}} = %{$Sub_SubProblems{$ProblemType}};
11377 }
11378 else {
11379 %{$Sub_SubProblems{"Field_Became_Const"}} = %{$Sub_SubProblems{$ProblemType}};
11380 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011381 }
11382 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
11383 {
11384 if($RR==2) {
11385 %{$Sub_SubProblems{"Field_Removed_Const"}} = %{$Sub_SubProblems{$ProblemType}};
11386 }
11387 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011388 %{$Sub_SubProblems{"Field_Became_Non_Const"}} = %{$Sub_SubProblems{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011389 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011390 }
11391 }
11392 }
11393
11394 if($Level eq "Source")
11395 {
11396 foreach my $ProblemType (keys(%Sub_SubProblems))
11397 {
11398 my $Old_Value = $Sub_SubProblems{$ProblemType}{"Old_Value"};
11399 my $New_Value = $Sub_SubProblems{$ProblemType}{"New_Value"};
11400
11401 if($ProblemType eq "Field_Type")
11402 {
11403 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011404 delete($Sub_SubProblems{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011405 }
11406 }
11407 }
11408 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011409
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011410 foreach my $ProblemType (keys(%Sub_SubProblems))
11411 {
11412 my $ProblemType_Init = $ProblemType;
11413 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011414 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011415 if(not isPublic(\%Type1_Pure, $Member_Pos)
11416 or isUnnamed($Member_Name)) {
11417 $ProblemType = "Private_".$ProblemType;
11418 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011419 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 +040011420 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011421 if($Type2_Pure{"Type"} ne "Union"
11422 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011423 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011424 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 +040011425 { # changed offset
11426 $ProblemType .= "_And_Layout";
11427 }
11428 }
11429 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11430 $ProblemType .= "_And_Type_Size";
11431 }
11432 }
11433 }
11434 else
11435 {
11436 if(not isPublic(\%Type1_Pure, $Member_Pos)
11437 or isUnnamed($Member_Name)) {
11438 next;
11439 }
11440 }
11441 if($ProblemType eq "Private_Field_Type_And_Size")
11442 { # private field change with no effect
11443 next;
11444 }
11445 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11446 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011447 "Type_Name"=>$Type1_Pure{"Name"});
11448
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011449 foreach my $Attr (keys(%{$Sub_SubProblems{$ProblemType_Init}}))
11450 { # other properties
11451 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubProblems{$ProblemType_Init}{$Attr};
11452 }
11453 }
11454 if(not isPublic(\%Type1_Pure, $Member_Pos))
11455 { # do NOT check internal type changes
11456 next;
11457 }
11458 if($MemberType1_Id and $MemberType2_Id)
11459 {# checking member type changes (replace)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011460 %Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011461 foreach my $Sub_SubProblemType (keys(%Sub_SubProblems))
11462 {
11463 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems{$Sub_SubProblemType}}))
11464 {
11465 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
11466 $SubProblems{$Sub_SubProblemType}{$NewLocation}{"IsInTypeInternals"}=1;
11467 foreach my $Attr (keys(%{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}})) {
11468 $SubProblems{$Sub_SubProblemType}{$NewLocation}{$Attr} = $Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr};
11469 }
11470 if($Sub_SubLocation!~/\-\>/) {
11471 $SubProblems{$Sub_SubProblemType}{$NewLocation}{"Start_Type_Name"} = $MemberType1_Name;
11472 }
11473 }
11474 }
11475 }
11476 }
11477 }
11478 }
11479 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11480 { # checking added members, public and private
11481 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11482 next if(not $Member_Name);
11483 if($AddedField{$Member_Pos})
11484 { # added
11485 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11486 {
11487 my $ProblemType = "Added_Field";
11488 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011489 or isUnnamed($Member_Name))
11490 {
11491 if($Level eq "Source") {
11492 next;
11493 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011494 $ProblemType = "Added_Private_Field";
11495 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011496 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011497 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011498 {
11499 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
11500 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011501 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 +040011502 { # changed offset
11503 $ProblemType .= "_And_Layout";
11504 }
11505 }
11506 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11507 $ProblemType .= "_And_Size";
11508 }
11509 }
11510 if($ProblemType eq "Added_Private_Field")
11511 { # skip added private fields
11512 next;
11513 }
11514 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11515 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011516 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011517 }
11518 elsif($Type2_Pure{"Type"} eq "Union")
11519 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011520 if($Level eq "Binary"
11521 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011522 {
11523 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
11524 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011525 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011526 }
11527 else
11528 {
11529 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
11530 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011531 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011532 }
11533 }
11534 elsif($Type2_Pure{"Type"} eq "Enum")
11535 {
11536 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
11537 next if($Member_Value eq "");
11538 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
11539 "Target"=>$Member_Name,
11540 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011541 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011542 }
11543 }
11544 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011545 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011546 pop(@RecurTypes);
11547 return %SubProblems;
11548}
11549
11550sub isUnnamed($) {
11551 return $_[0]=~/\Aunnamed\d+\Z/;
11552}
11553
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011554sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011555{
11556 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011557 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
11558 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
11559 $TypeName = uncover_typedefs($TypeName, $LibVersion);
11560 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011561 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011562 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011563 }
11564 return $TypeName;
11565}
11566
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011567sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011568{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011569 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011570 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011571 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
11572 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011573 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011574 return () if(not $TypeInfo{$LibVersion}{$TypeId});
11575 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011576 return () if(not $Type{"Type"});
11577 if($Type{"Type"} ne $Type_Type)
11578 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011579 return () if(not $Type{"BaseType"});
11580 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011581 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011582 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011583 return %Type;
11584}
11585
11586my %TypeSpecAttributes = (
11587 "Const" => 1,
11588 "Volatile" => 1,
11589 "ConstVolatile" => 1,
11590 "Restrict" => 1,
11591 "Typedef" => 1
11592);
11593
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011594sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011595{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011596 my ($TypeId, $Info) = @_;
11597 if(not $TypeId or not $Info
11598 or not $Info->{$TypeId}) {
11599 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011600 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011601 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
11602 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
11603 }
11604 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011605 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011606 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011607 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011608 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011609 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011610 return %Type;
11611}
11612
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011613sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011614{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011615 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011616 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011617 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
11618 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011619 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011620 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
11621 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011622 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
11623 my $PLevel = 0;
11624 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
11625 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011626 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011627 return $PLevel if(not $Type{"BaseType"});
11628 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
11629 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
11630 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011631}
11632
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011633sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011634{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011635 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011636 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011637 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
11638 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011639 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011640 return () if(not $TypeInfo{$LibVersion}{$TypeId});
11641 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011642 return %Type if(not $Type{"BaseType"});
11643 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011644 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011645 return %Type;
11646}
11647
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011648sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011649{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011650 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011651 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011652 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
11653 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011654 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011655 my $Qual = "";
11656 if($Type{"Type"} eq "Pointer") {
11657 $Qual .= "*";
11658 }
11659 elsif($Type{"Type"} eq "Ref") {
11660 $Qual .= "&";
11661 }
11662 elsif($Type{"Type"} eq "ConstVolatile") {
11663 $Qual .= "const volatile";
11664 }
11665 elsif($Type{"Type"} eq "Const"
11666 or $Type{"Type"} eq "Volatile"
11667 or $Type{"Type"} eq "Restrict") {
11668 $Qual .= lc($Type{"Type"});
11669 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011670 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011671 return $BQual.$Qual;
11672}
11673
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011674sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011675{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011676 my ($TypeId, $Info) = @_;
11677 if(not $TypeId or not $Info
11678 or not $Info->{$TypeId}) {
11679 return ();
11680 }
11681 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011682 return %Type if(not $Type{"BaseType"});
11683 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011684 {
11685 if($Info->{$BTid}) {
11686 return %{$Info->{$BTid}};
11687 }
11688 else { # something is going wrong
11689 return ();
11690 }
11691 }
11692 else {
11693 return %Type;
11694 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011695}
11696
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011697sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011698{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011699 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011700 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011701 return () if(not $TypeInfo{$LibVersion}{$TypeId});
11702 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011703}
11704
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040011705sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011706{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011707 my $Symbol = $_[0];
11708 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
11709}
11710
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011711sub isInLineInst($$$) {
11712 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
11713}
11714
11715sub isTemplateInstance($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011716{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011717 my ($Symbol, $SInfo, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011718 if($CheckObjectsOnly)
11719 {
11720 if($Symbol!~/\A(_Z|\?)/) {
11721 return 0;
11722 }
11723 if(my $Signature = $tr_name{$Symbol})
11724 {
11725 if(index($Signature,">")==-1) {
11726 return 0;
11727 }
11728 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
11729 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011730 if(index($ShortName,"<")!=-1
11731 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011732 return 1;
11733 }
11734 }
11735 }
11736 }
11737 else
11738 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011739 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011740 {
11741 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
11742 {
11743 if(index($ClassName,"<")!=-1) {
11744 return 1;
11745 }
11746 }
11747 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011748 if(my $ShortName = $SInfo->{"ShortName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011749 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011750 if(index($ShortName,"<")!=-1
11751 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011752 return 1;
11753 }
11754 }
11755 }
11756 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011757}
11758
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011759sub isTemplateSpec($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011760{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011761 my ($Symbol, $SInfo, $LibVersion) = @_;
11762 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011763 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011764 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011765 { # class specialization
11766 return 1;
11767 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011768 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011769 { # method specialization
11770 return 1;
11771 }
11772 }
11773 return 0;
11774}
11775
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011776sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011777{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011778 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040011779 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011780 { # non-public global data
11781 return 0;
11782 }
11783 if($CheckObjectsOnly) {
11784 return 0 if($Symbol=~/\A(_init|_fini)\Z/);
11785 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011786 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011787 { # support for old ABI dumps in --headers-only mode
11788 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
11789 {
11790 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
11791 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011792 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011793 if(not $PType or $PType eq "Unknown") {
11794 return 0;
11795 }
11796 }
11797 }
11798 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011799 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011800 {
11801 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011802 if($SkipSymbols{$LibVersion}{$Symbol})
11803 { # user defined symbols to ignore
11804 return 0;
11805 }
11806 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
11807 if(not $NameSpace and $ClassId)
11808 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011809 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011810 }
11811 if($NameSpace)
11812 { # user defined namespaces to ignore
11813 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
11814 return 0;
11815 }
11816 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
11817 { # nested namespaces
11818 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
11819 return 0;
11820 }
11821 }
11822 }
11823 if(my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
11824 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011825 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011826 { # --skip-headers or <skip_headers> (not <skip_including>)
11827 if($Skip==1) {
11828 return 0;
11829 }
11830 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011831 }
11832 if($SymbolsListPath and not $SymbolsList{$Symbol})
11833 { # user defined symbols
11834 return 0;
11835 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011836 if($SkipSymbolsListPath and $SkipSymbolsList{$Symbol})
11837 { # user defined symbols
11838 return 0;
11839 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011840 if($AppPath and not $SymbolsList_App{$Symbol})
11841 { # user defined symbols (in application)
11842 return 0;
11843 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011844 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
11845 { # non-target symbols
11846 return 0;
11847 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011848 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011849 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011850 if($CheckObjectsOnly)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011851 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011852 if(isTemplateInstance($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011853 return 0;
11854 }
11855 }
11856 else
11857 {
11858 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011859 or isInLineInst($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011860 {
11861 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
11862 { # inline virtual methods
11863 if($Type=~/InlineVirt/) {
11864 return 1;
11865 }
11866 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
11867 if(not $Allocable)
11868 { # check bases
11869 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
11870 {
11871 if(not isCopyingClass($DCId, $LibVersion))
11872 { # exists a derived class without default c-tor
11873 $Allocable=1;
11874 last;
11875 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011876 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011877 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011878 if(not $Allocable) {
11879 return 0;
11880 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011881 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011882 else
11883 { # inline non-virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011884 return 0;
11885 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011886 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011887 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011888 }
11889 }
11890 return 1;
11891}
11892
11893sub mergeImpl()
11894{
11895 my $DiffCmd = get_CmdPath("diff");
11896 if(not $DiffCmd) {
11897 exitStatus("Not_Found", "can't find \"diff\"");
11898 }
11899 foreach my $Interface (sort keys(%{$Symbol_Library{1}}))
11900 { # implementation changes
11901 next if($CompleteSignature{1}{$Interface}{"Private"});
11902 next if(not $CompleteSignature{1}{$Interface}{"Header"} and not $CheckObjectsOnly);
11903 next if(not $Symbol_Library{2}{$Interface} and not $Symbol_Library{2}{$SymVer{2}{$Interface}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011904 if(not symbolFilter($Interface, 1, "Affected", "Binary")) {
11905 next;
11906 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011907 my $Impl1 = canonifyImpl($Interface_Impl{1}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011908 next if(not $Impl1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011909 my $Impl2 = canonifyImpl($Interface_Impl{2}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011910 next if(not $Impl2);
11911 if($Impl1 ne $Impl2)
11912 {
11913 writeFile("$TMP_DIR/impl1", $Impl1);
11914 writeFile("$TMP_DIR/impl2", $Impl2);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040011915 my $Diff = `$DiffCmd -rNau \"$TMP_DIR/impl1\" \"$TMP_DIR/impl2\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011916 $Diff=~s/(---|\+\+\+).+\n//g;
11917 $Diff=~s/[ ]{3,}/ /g;
11918 $Diff=~s/\n\@\@/\n \n\@\@/g;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040011919 unlink("$TMP_DIR/impl1");
11920 unlink("$TMP_DIR/impl2");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011921 %{$CompatProblems_Impl{$Interface}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011922 "Diff" => get_CodeView($Diff) );
11923 }
11924 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011925
11926 # clean memory
11927 %Interface_Impl = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011928}
11929
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011930sub canonifyImpl($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011931{
11932 my $FuncBody= $_[0];
11933 return "" if(not $FuncBody);
11934 $FuncBody=~s/0x[a-f\d]+/0x?/g;# addr
11935 $FuncBody=~s/((\A|\n)[a-z]+[\t ]+)[a-f\d]+([^x]|\Z)/$1?$3/g;# call, jump
11936 $FuncBody=~s/# [a-f\d]+ /# ? /g;# call, jump
11937 $FuncBody=~s/%([a-z]+[a-f\d]*)/\%reg/g;# registers
11938 while($FuncBody=~s/\nnop[ \t]*(\n|\Z)/$1/g){};# empty op
11939 $FuncBody=~s/<.+?\.cpp.+?>/<name.cpp>/g;
11940 $FuncBody=~s/(\A|\n)[a-f\d]+ </$1? </g;# 5e74 <_ZN...
11941 $FuncBody=~s/\.L\d+/.L/g;
11942 $FuncBody=~s/#(-?)\d+/#$1?/g;# r3, [r3, #120]
11943 $FuncBody=~s/[\n]{2,}/\n/g;
11944 return $FuncBody;
11945}
11946
11947sub get_CodeView($)
11948{
11949 my $Code = $_[0];
11950 my $View = "";
11951 foreach my $Line (split(/\n/, $Code))
11952 {
11953 if($Line=~s/\A(\+|-)/$1 /g)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011954 { # bold line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011955 $View .= "<tr><td><b>".htmlSpecChars($Line)."</b></td></tr>\n";
11956 }
11957 else {
11958 $View .= "<tr><td>".htmlSpecChars($Line)."</td></tr>\n";
11959 }
11960 }
11961 return "<table class='code_view'>$View</table>\n";
11962}
11963
11964sub getImplementations($$)
11965{
11966 my ($LibVersion, $Path) = @_;
11967 return if(not $LibVersion or not -e $Path);
11968 if($OSgroup eq "macos")
11969 {
11970 my $OtoolCmd = get_CmdPath("otool");
11971 if(not $OtoolCmd) {
11972 exitStatus("Not_Found", "can't find \"otool\"");
11973 }
11974 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040011975 foreach my $Line (split(/\n/, `$OtoolCmd -tv \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011976 {
11977 if($Line=~/\A\s*_(\w+)\s*:/i) {
11978 $CurInterface = $1;
11979 }
11980 elsif($Line=~/\A\s*[\da-z]+\s+(.+?)\Z/i) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011981 $Interface_Impl{$LibVersion}{$CurInterface} .= $1."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011982 }
11983 }
11984 }
11985 else
11986 {
11987 my $ObjdumpCmd = get_CmdPath("objdump");
11988 if(not $ObjdumpCmd) {
11989 exitStatus("Not_Found", "can't find \"objdump\"");
11990 }
11991 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040011992 foreach my $Line (split(/\n/, `$ObjdumpCmd -d \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011993 {
11994 if($Line=~/\A[\da-z]+\s+<(\w+)>/i) {
11995 $CurInterface = $1;
11996 }
11997 else
11998 { # x86: 51fa:(\t)89 e5 (\t)mov %esp,%ebp
11999 # arm: 5020:(\t)e24cb004(\t)sub(\t)fp, ip, #4(\t); 0x4
12000 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 +040012001 $Interface_Impl{$LibVersion}{$CurInterface} .= $2."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012002 }
12003 }
12004 }
12005 }
12006}
12007
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012008sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012009{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012010 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012011 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12012 {
12013 if(link_symbol($Symbol, 1, "+Deps"))
12014 { # linker can find a new symbol
12015 # in the old-version library
12016 # So, it's not a new symbol
12017 next;
12018 }
12019 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012020 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012021 next;
12022 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012023 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012024 }
12025}
12026
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012027sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012028{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012029 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012030 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12031 {
12032 if($CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012033 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012034 }
12035 if(link_symbol($Symbol, 2, "+Deps"))
12036 { # linker can find an old symbol
12037 # in the new-version library
12038 next;
12039 }
12040 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012041 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012042 next;
12043 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012044 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012045 }
12046}
12047
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012048sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012049{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012050 my $Level = $_[0];
12051 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012052 { # checking added symbols
12053 next if($CompleteSignature{2}{$Symbol}{"Private"});
12054 next if(not $CompleteSignature{2}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012055 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012056 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012057 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012058 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012059 { # checking removed symbols
12060 next if($CompleteSignature{1}{$Symbol}{"Private"});
12061 next if(not $CompleteSignature{1}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012062 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012063 { # skip v-tables for templates, that should not be imported by applications
12064 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012065 if(my $CName = $VTableClass{$Symbol})
12066 {
12067 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12068 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012069 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012070 next;
12071 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012072 }
12073 }
12074 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012075 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012076 }
12077 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12078 { # symbols for pure virtual methods cannot be called by clients
12079 next;
12080 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012081 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012082 }
12083}
12084
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012085sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012086{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012087 my ($LibVersion, $V) = @_;
12088 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12089 return $Cache{"checkDump"}{$LibVersion}{$V};
12090 }
12091 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012092}
12093
12094sub detectAdded_H($)
12095{
12096 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012097 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12098 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012099 if($Level eq "Source")
12100 { # remove symbol version
12101 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12102 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012103
12104 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12105 { # skip artificial constructors
12106 next;
12107 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012108 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012109 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12110 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012111 next;
12112 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012113 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012114 next;
12115 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012116 if(not defined $CompleteSignature{1}{$Symbol}
12117 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12118 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012119 if($UsedDump{2}{"SrcBin"})
12120 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012121 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012122 { # support for old and different (!) ABI dumps
12123 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12124 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012125 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012126 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012127 {
12128 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12129 {
12130 if($Lang eq "C")
12131 { # support for old ABI dumps: missed extern "C" functions
12132 next;
12133 }
12134 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012135 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012136 else
12137 {
12138 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012139 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012140 next;
12141 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012142 }
12143 }
12144 }
12145 }
12146 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012147 }
12148 }
12149}
12150
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012151sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012152{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012153 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012154 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12155 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012156 if($Level eq "Source")
12157 { # remove symbol version
12158 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12159 $Symbol=$SN;
12160 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012161 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12162 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012163 next;
12164 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012165 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012166 next;
12167 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012168 if(not defined $CompleteSignature{2}{$Symbol}
12169 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012170 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012171 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012172 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012173 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012174 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012175 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12176 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012177 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012178 if($CheckHeadersOnly)
12179 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012180 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12181 {
12182 if($Lang eq "C")
12183 { # support for old ABI dumps: missed extern "C" functions
12184 next;
12185 }
12186 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012187 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012188 else
12189 {
12190 if(not link_symbol($Symbol, 1, "-Deps"))
12191 { # skip removed inline symbols
12192 next;
12193 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012194 }
12195 }
12196 }
12197 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012198 if(not checkDump(1, "2.15"))
12199 {
12200 if($Symbol=~/_IT_E\Z/)
12201 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12202 next;
12203 }
12204 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012205 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12206 {
12207 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12208 {
12209 if(defined $Constants{2}{$Short})
12210 {
12211 my $Val = $Constants{2}{$Short}{"Value"};
12212 if(defined $Func_ShortName{2}{$Val})
12213 { # old name defined to new
12214 next;
12215 }
12216 }
12217 }
12218
12219 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012220 $RemovedInt{$Level}{$Symbol} = 1;
12221 if($Level eq "Source")
12222 { # search for a source-compatible equivalent
12223 setAlternative($Symbol, $Level);
12224 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012225 }
12226 }
12227}
12228
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012229sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012230{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012231 my $Level = $_[0];
12232 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012233 { # checking added symbols
12234 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012235 next if($CompleteSignature{2}{$Symbol}{"Private"});
12236 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012237 if($Level eq "Binary")
12238 {
12239 if($CompleteSignature{2}{$Symbol}{"InLine"})
12240 {
12241 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12242 { # skip inline non-virtual functions
12243 next;
12244 }
12245 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012246 }
12247 else
12248 { # Source
12249 if($SourceAlternative_B{$Symbol}) {
12250 next;
12251 }
12252 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012253 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012254 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012255 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012256 { # checking removed symbols
12257 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012258 next if($CompleteSignature{1}{$Symbol}{"Private"});
12259 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012260 if($Level eq "Binary")
12261 {
12262 if($CompleteSignature{1}{$Symbol}{"InLine"})
12263 {
12264 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
12265 { # skip inline non-virtual functions
12266 next;
12267 }
12268 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012269 }
12270 else
12271 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012272 if(my $Alt = $SourceAlternative{$Symbol})
12273 {
12274 if(defined $CompleteSignature{1}{$Alt}
12275 and $CompleteSignature{1}{$Symbol}{"Const"})
12276 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012277 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012278 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012279 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012280 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012281 }
12282 else
12283 { # do NOT show removed symbol
12284 next;
12285 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012286 }
12287 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012288 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012289 }
12290}
12291
12292sub addParamNames($)
12293{
12294 my $LibraryVersion = $_[0];
12295 return if(not keys(%AddIntParams));
12296 my $SecondVersion = $LibraryVersion==1?2:1;
12297 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
12298 {
12299 next if(not keys(%{$AddIntParams{$Interface}}));
12300 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012301 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012302 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
12303 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012304 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012305 if(defined $CompleteSignature{$SecondVersion}{$Interface}
12306 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
12307 {
12308 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
12309 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12310 }
12311 }
12312 else {
12313 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12314 }
12315 }
12316 }
12317 }
12318}
12319
12320sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012321{ # detect changed typedefs to show
12322 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012323 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
12324 {
12325 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012326 my $BName1 = $Typedef_BaseName{1}{$Typedef};
12327 if(not $BName1 or isAnon($BName1)) {
12328 next;
12329 }
12330 my $BName2 = $Typedef_BaseName{2}{$Typedef};
12331 if(not $BName2 or isAnon($BName2)) {
12332 next;
12333 }
12334 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012335 $ChangedTypedef{$Typedef} = 1;
12336 }
12337 }
12338}
12339
12340sub get_symbol_suffix($$)
12341{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012342 my ($Symbol, $Full) = @_;
12343 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040012344 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012345 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012346 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012347 if(not $Full) {
12348 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
12349 }
12350 return $Suffix;
12351}
12352
12353sub get_symbol_prefix($$)
12354{
12355 my ($Symbol, $LibVersion) = @_;
12356 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
12357 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12358 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012359 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012360 }
12361 return $ShortName;
12362}
12363
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012364sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012365{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012366 my $Symbol = $_[0];
12367 my $PSymbol = $Symbol;
12368 if(not defined $CompleteSignature{2}{$PSymbol}
12369 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
12370 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
12371 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012372 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012373 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012374 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012375 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012376 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
12377 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012378 {
12379 if(defined $CompleteSignature{2}{$PSymbol}
12380 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12381 {
12382 $SourceAlternative{$Symbol} = $PSymbol;
12383 $SourceAlternative_B{$PSymbol} = $Symbol;
12384 if(not defined $CompleteSignature{1}{$PSymbol}
12385 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12386 $SourceReplacement{$Symbol} = $PSymbol;
12387 }
12388 }
12389 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012390 }
12391 else
12392 {
12393 foreach my $Sp ("KV", "VK", "K", "V")
12394 {
12395 if($PSymbol=~s/\A_ZN$Sp/_ZN/
12396 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
12397 {
12398 if(defined $CompleteSignature{2}{$PSymbol}
12399 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12400 {
12401 $SourceAlternative{$Symbol} = $PSymbol;
12402 $SourceAlternative_B{$PSymbol} = $Symbol;
12403 if(not defined $CompleteSignature{1}{$PSymbol}
12404 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12405 $SourceReplacement{$Symbol} = $PSymbol;
12406 }
12407 }
12408 }
12409 $PSymbol = $Symbol;
12410 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012411 }
12412 }
12413 }
12414 return "";
12415}
12416
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012417sub getSymKind($$)
12418{
12419 my ($Symbol, $LibVersion) = @_;
12420 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
12421 {
12422 return "Global_Data";
12423 }
12424 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12425 {
12426 return "Method";
12427 }
12428 return "Function";
12429}
12430
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040012431sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012432{
12433 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012434 my %SubProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012435
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012436 mergeBases($Level);
12437
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012438 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012439 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012440 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012441 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012442 next;
12443 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012444 if(defined $CompleteSignature{1}{$Symbol}
12445 and $CompleteSignature{1}{$Symbol}{"Header"})
12446 { # double-check added symbol
12447 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012448 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012449 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012450 next;
12451 }
12452 if($Symbol=~/\A(_Z|\?)/)
12453 { # C++
12454 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
12455 }
12456 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
12457 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012458 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
12459 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012460 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012461 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012462 {
12463 if($TName_Tid{1}{$AffectedClass_Name})
12464 { # class should exist in previous version
12465 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
12466 { # old v-table is NOT copied by old applications
12467 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
12468 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012469 "Target"=>get_Signature($Symbol, 2),
12470 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012471 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012472 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012473 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012474 }
12475 }
12476 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012477 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
12478 { # check all removed exported symbols
12479 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012480 next;
12481 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012482 if(defined $CompleteSignature{2}{$Symbol}
12483 and $CompleteSignature{2}{$Symbol}{"Header"})
12484 { # double-check removed symbol
12485 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012486 }
12487 if($CompleteSignature{1}{$Symbol}{"Private"})
12488 { # skip private methods
12489 next;
12490 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012491 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012492 next;
12493 }
12494 $CheckedSymbols{$Level}{$Symbol} = 1;
12495 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
12496 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012497 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
12498 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012499 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012500 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
12501 {
12502 if($TName_Tid{2}{$AffectedClass_Name})
12503 { # class should exist in newer version
12504 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
12505 { # old v-table is NOT copied by old applications
12506 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
12507 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012508 "Target"=>get_Signature($OverriddenMethod, 1),
12509 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012510 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012511 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012512 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012513 }
12514 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012515 if($Level eq "Binary"
12516 and $OSgroup eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012517 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012518 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012519 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012520 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012521 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012522 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012523 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012524 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012525 {
12526 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
12527 "Target"=>$tr_name{$Symbol},
12528 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012529 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012530 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012531 else
12532 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012533 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012534 "Target"=>$tr_name{$Symbol},
12535 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012536 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012537 }
12538 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012539 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012540 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012541 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012542 {
12543 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
12544 "Target"=>$tr_name{$Symbol},
12545 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012546 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012547 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012548 else
12549 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012550 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012551 "Target"=>$tr_name{$Symbol},
12552 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012553 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012554 }
12555 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012556 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
12557 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
12558 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
12559 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
12560 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012561 {
12562 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012563 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012564 $ProblemType = "Global_Data_Symbol_Changed_Type";
12565 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012566 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
12567 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012568 "Old_Type"=>$RTName1,
12569 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012570 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012571 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012572 }
12573 }
12574 }
12575 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012576 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012577 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012578 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012579 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012580 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012581 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012582 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012583 if($CompleteSignature{1}{$Symbol}{"Constructor"})
12584 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012585 if($Symbol=~/(C1E|C2E)/)
12586 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012587 my $CtorType = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012588 $NewSym=~s/(C1E|C2E)/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012589 }
12590 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012591 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
12592 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012593 if($Symbol=~/(D0E|D1E|D2E)/)
12594 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012595 my $DtorType = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012596 $NewSym=~s/(D0E|D1E|D2E)/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012597 }
12598 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012599 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012600 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012601 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012602 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012603 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012604 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012605 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012606 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012607 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012608 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012609 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012610 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012611 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012612 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012613 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012614 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012615 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012616 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012617 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012618 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012619 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012620 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012621 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012622 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012623 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012624 { # "volatile" to non-"volatile"
12625
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012626 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012627 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012628 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012629 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012630 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012631 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012632 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012633 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012634 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012635 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012636 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012637 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012638 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012639 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012640 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012641 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012642 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012643 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
12644 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012645 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012646 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012647 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012648 }
12649 }
12650 }
12651 }
12652 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012653 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12654 { # checking symbols
12655 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12656 if($Level eq "Source")
12657 { # remove symbol version
12658 $Symbol=$SN;
12659 }
12660 else
12661 { # Binary
12662 if(not $SV)
12663 { # symbol without version
12664 if(my $VSym = $SymVer{1}{$Symbol})
12665 { # the symbol is linked with versioned symbol
12666 if($CompleteSignature{2}{$VSym}{"MnglName"})
12667 { # show report for symbol@ver only
12668 next;
12669 }
12670 elsif(not link_symbol($VSym, 2, "-Deps"))
12671 { # changed version: sym@v1 to sym@v2
12672 # do NOT show report for symbol
12673 next;
12674 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012675 }
12676 }
12677 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012678 my $PSymbol = $Symbol;
12679 if($Level eq "Source"
12680 and my $S = $SourceReplacement{$Symbol})
12681 { # take a source-compatible replacement function
12682 $PSymbol = $S;
12683 }
12684 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012685 { # private symbols
12686 next;
12687 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012688 if(not defined $CompleteSignature{1}{$Symbol}
12689 or not defined $CompleteSignature{2}{$PSymbol})
12690 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012691 next;
12692 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012693 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
12694 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
12695 { # no mangled name
12696 next;
12697 }
12698 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12699 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012700 { # without a header
12701 next;
12702 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012703
12704 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
12705 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
12706 { # became pure
12707 next;
12708 }
12709 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
12710 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
12711 { # became non-pure
12712 next;
12713 }
12714
12715 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
12716 { # exported, target, inline virtual and pure virtual
12717 next;
12718 }
12719 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
12720 { # exported, target, inline virtual and pure virtual
12721 next;
12722 }
12723
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012724 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012725 {
12726 if($CompleteSignature{1}{$Symbol}{"Data"}
12727 and $CompleteSignature{2}{$PSymbol}{"Data"})
12728 {
12729 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
12730 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
12731 if(defined $Value1)
12732 {
12733 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
12734 if(defined $Value2)
12735 {
12736 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
12737 if($Value1 ne $Value2)
12738 {
12739 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
12740 "Old_Value"=>$Value1,
12741 "New_Value"=>$Value2,
12742 "Target"=>get_Signature($Symbol, 1) );
12743 }
12744 }
12745 }
12746 }
12747 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012748
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012749 if($CompleteSignature{2}{$PSymbol}{"Private"})
12750 {
12751 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
12752 "Target"=>get_Signature_M($PSymbol, 2) );
12753 }
12754 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
12755 and $CompleteSignature{2}{$PSymbol}{"Protected"})
12756 {
12757 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
12758 "Target"=>get_Signature_M($PSymbol, 2) );
12759 }
12760 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
12761 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
12762 {
12763 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
12764 "Target"=>get_Signature_M($PSymbol, 2) );
12765 }
12766
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012767 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012768 mergeVirtualTables($Symbol, $Level);
12769
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012770 if($COMPILE_ERRORS)
12771 { # if some errors occurred at the compiling stage
12772 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012773 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012774 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012775 { # missed information about parameters in newer version
12776 next;
12777 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012778 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012779 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012780 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012781 next;
12782 }
12783 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012784 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012785 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012786 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012787 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
12788 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012789 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
12790 "Target"=>get_Signature($Symbol, 1)
12791 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012792 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012793 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012794 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
12795 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012796 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012797 "Target"=>get_Signature($Symbol, 1)
12798 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012799 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012800 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
12801 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012802 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012803 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012804 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012805 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
12806 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
12807 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012808 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012809 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012810 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
12811 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012812 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012813 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012814 my $ProblemType = "Virtual_Method_Position";
12815 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
12816 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012817 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012818 if(isUsedClass($Class_Id, 1, $Level))
12819 {
12820 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012821 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012822 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012823 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
12824 next;
12825 }
12826 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012827 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012828 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
12829 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012830 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012831 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012832 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012833 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012834 }
12835 }
12836 }
12837 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012838 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
12839 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012840 { # do NOT check type changes in pure virtuals
12841 next;
12842 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012843 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012844 if($Symbol=~/\A(_Z|\?)/
12845 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012846 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012847 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012848 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012849 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012850 }
12851 }
12852 else
12853 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012854 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012855 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012856 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012857 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
12858 last if($PType2_Name eq "...");
12859 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
12860 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012861 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012862 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012863 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012864 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
12865 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012866 if($#Positions1==-1 or $#Positions2>$#Positions1) {
12867 $ParamPos_Prev = "lost";
12868 }
12869 }
12870 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012871 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012872 }
12873 if($ParamPos_Prev eq "lost")
12874 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012875 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012876 {
12877 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012878 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012879 $ProblemType = "Added_Unnamed_Parameter";
12880 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012881 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012882 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012883 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012884 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012885 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012886 }
12887 else
12888 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012889 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012890 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012891 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012892 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
12893 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012894 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012895 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012896 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012897 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012898 "Target"=>$PName_Old,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012899 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012900 "Param_Type"=>$PType2_Name,
12901 "Old_Value"=>$PName_Old,
12902 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012903 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012904 }
12905 }
12906 else
12907 {
12908 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012909 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012910 $ProblemType = "Added_Middle_Unnamed_Parameter";
12911 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012912 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012913 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012914 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012915 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012916 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012917 }
12918 }
12919 }
12920 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012921 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012922 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012923 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012924 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012925 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012926 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012927 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012928 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012929 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012930 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
12931 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012932 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012933 }
12934 }
12935 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012936 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012937 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012938 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012939 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
12940 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012941 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
12942 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012943 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012944 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012945 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012946 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
12947 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012948 if($#Positions2==-1 or $#Positions2<$#Positions1) {
12949 $ParamPos_New = "lost";
12950 }
12951 }
12952 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012953 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012954 }
12955 if($ParamPos_New eq "lost")
12956 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012957 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012958 {
12959 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012960 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012961 $ProblemType = "Removed_Unnamed_Parameter";
12962 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012963 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012964 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012965 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012966 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012967 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012968 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012969 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012970 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012971 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012972 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012973 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012974 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012975 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012976 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012977 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012978 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012979 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012980 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012981 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012982 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012983 "Old_Value"=>$PName,
12984 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012985 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012986 }
12987 }
12988 else
12989 {
12990 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012991 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012992 $ProblemType = "Removed_Middle_Unnamed_Parameter";
12993 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012994 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012995 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012996 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012997 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012998 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012999 }
13000 }
13001 }
13002 }
13003 }
13004 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013005 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13006 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
13007 %SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013008
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013009 foreach my $SubProblemType (keys(%SubProblems))
13010 {
13011 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13012 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013013 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013014
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013015 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013016 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013017 if($SubProblemType eq "Return_Type_And_Size") {
13018 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13019 }
13020 elsif($SubProblemType eq "Return_Type_Format") {
13021 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13022 }
13023 else {
13024 $ProblemTypes{"Global_Data_Type"} = 1;
13025 }
13026
13027 # quals
13028 if($SubProblemType eq "Return_Type"
13029 or $SubProblemType eq "Return_Type_And_Size"
13030 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013031 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013032 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13033 { # const to non-const
13034 if($RR==2) {
13035 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13036 }
13037 else {
13038 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13039 }
13040 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013041 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013042 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13043 { # non-const to const
13044 if($RA==2) {
13045 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13046 }
13047 else {
13048 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13049 }
13050 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013051 }
13052 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013053 }
13054 else
13055 {
13056 # quals
13057 if($SubProblemType eq "Return_Type"
13058 or $SubProblemType eq "Return_Type_And_Size"
13059 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013060 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013061 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013062 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013063 if(addedQual($Old_Value, $New_Value, "volatile"))
13064 {
13065 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13066 if($Level ne "Source"
13067 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13068 $ProblemTypes{"Return_Type"} = 1;
13069 }
13070 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013071 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013072 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13073 {
13074 if($RA==2) {
13075 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13076 }
13077 else {
13078 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13079 }
13080 if($Level ne "Source"
13081 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13082 $ProblemTypes{"Return_Type"} = 1;
13083 }
13084 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013085 }
13086 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013087 if($Level eq "Binary"
13088 and not $CompleteSignature{1}{$Symbol}{"Data"})
13089 {
13090 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13091 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13092 { # if one of the architectures is unknown
13093 # then set other arhitecture to unknown too
13094 ($Arch1, $Arch2) = ("unknown", "unknown");
13095 }
13096 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013097 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013098 {
13099 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13100 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13101 }
13102 else
13103 {
13104 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13105 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13106 }
13107
13108 if($SubProblemType eq "Return_Type_Became_Void")
13109 {
13110 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13111 { # parameters stack has been affected
13112 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013113 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013114 }
13115 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013116 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013117 }
13118 }
13119 }
13120 elsif($SubProblemType eq "Return_Type_From_Void")
13121 {
13122 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13123 { # parameters stack has been affected
13124 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013125 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013126 }
13127 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013128 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013129 }
13130 }
13131 }
13132 elsif($SubProblemType eq "Return_Type"
13133 or $SubProblemType eq "Return_Type_And_Size"
13134 or $SubProblemType eq "Return_Type_Format")
13135 {
13136 if($Conv1{"Method"} ne $Conv2{"Method"})
13137 {
13138 if($Conv1{"Method"} eq "stack")
13139 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013140 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013141 }
13142 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013143 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013144 }
13145 }
13146 else
13147 {
13148 if($Conv1{"Method"} eq "reg")
13149 {
13150 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13151 {
13152 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013153 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013154 }
13155 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013156 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013157 }
13158 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013159 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013160 }
13161 }
13162 }
13163 }
13164 }
13165 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013166
13167 if(not keys(%ProblemTypes))
13168 { # default
13169 $ProblemTypes{$SubProblemType} = 1;
13170 }
13171
13172 foreach my $ProblemType (keys(%ProblemTypes))
13173 { # additional
13174 @{$CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013175 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013176 }
13177 if($ReturnType1_Id and $ReturnType2_Id)
13178 {
13179 @RecurTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013180 %SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013181
13182 if($CompleteSignature{1}{$Symbol}{"Data"})
13183 {
13184 if($Level eq "Binary")
13185 {
13186 if(get_PLevel($ReturnType1_Id, 1)==0)
13187 {
13188 foreach my $SubProblemType (keys(%SubProblems))
13189 { # add "Global_Data_Size" problem
13190 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13191 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
13192 if($SubProblemType eq "DataType_Size")
13193 { # add a new problem
13194 %{$SubProblems{"Global_Data_Size"}} = %{$SubProblems{$SubProblemType}};
13195 }
13196 }
13197 }
13198 if(not defined $SubProblems{"Global_Data_Size"})
13199 {
13200 if(defined $GlobalDataObject{1}{$Symbol}
13201 and defined $GlobalDataObject{2}{$Symbol})
13202 {
13203 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13204 my $New_Size = $GlobalDataObject{2}{$Symbol};
13205 if($Old_Size!=$New_Size)
13206 {
13207 %{$SubProblems{"Global_Data_Size"}{"retval"}} = (
13208 "Old_Size"=>$Old_Size*$BYTE_SIZE,
13209 "New_Size"=>$New_Size*$BYTE_SIZE );
13210 }
13211 }
13212 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013213 }
13214 }
13215 foreach my $SubProblemType (keys(%SubProblems))
13216 {
13217 foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}}))
13218 {
13219 my $NewLocation = ($SubLocation)?"retval->".$SubLocation:"retval";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013220 %{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013221 "Return_Type_Name"=>$TypeInfo{1}{$ReturnType1_Id}{"Name"} );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013222 @{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013223 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013224 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$ReturnType1_Id}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013225 }
13226 }
13227 }
13228 }
13229
13230 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013231 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13232 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13233 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013234 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013235 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013236 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13237 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013238 if($ThisPtr1_Id and $ThisPtr2_Id)
13239 {
13240 @RecurTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013241 %SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013242 foreach my $SubProblemType (keys(%SubProblems))
13243 {
13244 foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}}))
13245 {
13246 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013247 %{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013248 "Object_Type_Name"=>$TypeInfo{1}{$ObjTId1}{"Name"} );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013249 @{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013250 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013251 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$ObjTId1}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013252 }
13253 }
13254 }
13255 }
13256 }
13257 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013258 if($Level eq "Binary") {
13259 mergeVTables($Level);
13260 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013261 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
13262 $CheckedSymbols{$Level}{$Symbol} = 1;
13263 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013264}
13265
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013266sub rmQuals($$)
13267{
13268 my ($Value, $Qual) = @_;
13269 if(not $Qual) {
13270 return $Value;
13271 }
13272 if($Qual eq "all")
13273 { # all quals
13274 $Qual = "const|volatile|restrict";
13275 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013276 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013277 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013278 }
13279 return $Value;
13280}
13281
13282sub cmpBTypes($$$$)
13283{
13284 my ($T1, $T2, $V1, $V2) = @_;
13285 $T1 = uncover_typedefs($T1, $V1);
13286 $T2 = uncover_typedefs($T2, $V2);
13287 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
13288}
13289
13290sub addedQual($$$)
13291{
13292 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013293 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013294}
13295
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013296sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013297{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013298 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013299 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013300}
13301
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013302sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013303{
13304 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
13305 $Old_Value = uncover_typedefs($Old_Value, $V1);
13306 $New_Value = uncover_typedefs($New_Value, $V2);
13307 if($Old_Value eq $New_Value)
13308 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013309 return 0;
13310 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013311 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013312 { # without a qual
13313 return 0;
13314 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013315 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013316 { # became non-qual
13317 return 1;
13318 }
13319 else
13320 {
13321 my @BQ1 = getQualModel($Old_Value, $Qual);
13322 my @BQ2 = getQualModel($New_Value, $Qual);
13323 foreach (0 .. $#BQ1)
13324 { # removed qual
13325 if($BQ1[$_]==1
13326 and $BQ2[$_]!=1)
13327 {
13328 return 2;
13329 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013330 }
13331 }
13332 return 0;
13333}
13334
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013335sub getQualModel($$)
13336{
13337 my ($Value, $Qual) = @_;
13338 if(not $Qual) {
13339 return $Value;
13340 }
13341
13342 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013343 while($Value=~/(\w+)/ and $1 ne $Qual) {
13344 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013345 }
13346 $Value=~s/[^\*\&\w]+//g;
13347
13348 # modeling
13349 # int*const*const == 011
13350 # int**const == 001
13351 my @Model = ();
13352 my @Elems = split(/[\*\&]/, $Value);
13353 if(not @Elems) {
13354 return (0);
13355 }
13356 foreach (@Elems)
13357 {
13358 if($_ eq $Qual) {
13359 push(@Model, 1);
13360 }
13361 else {
13362 push(@Model, 0);
13363 }
13364 }
13365
13366 return @Model;
13367}
13368
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013369my %StringTypes = map {$_=>1} (
13370 "char*",
13371 "char const*"
13372);
13373
13374my %CharTypes = map {$_=>1} (
13375 "char",
13376 "char const"
13377);
13378
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013379sub showVal($$$)
13380{
13381 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013382 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040013383 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040013384 if(substr($Value, 0, 2) eq "_Z")
13385 {
13386 if(my $Unmangled = $tr_name{$Value}) {
13387 return $Unmangled;
13388 }
13389 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013390 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013391 { # strings
13392 return "\"$Value\"";
13393 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013394 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013395 { # characters
13396 return "\'$Value\'";
13397 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013398 if($Value eq "")
13399 { # other
13400 return "\'\'";
13401 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013402 return $Value;
13403}
13404
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013405sub getRegs($$$)
13406{
13407 my ($LibVersion, $Symbol, $Pos) = @_;
13408
13409 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
13410 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013411 my %Regs = ();
13412 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
13413 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013414 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013415 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
13416 }
13417 }
13418
13419 return join(", ", sort keys(%Regs));
13420 }
13421
13422 return undef;
13423}
13424
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013425sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013426{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013427 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013428 if(not $Symbol) {
13429 return;
13430 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013431 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
13432 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
13433 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
13434 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013435 if(not $PType1_Id
13436 or not $PType2_Id) {
13437 return;
13438 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013439
13440 if(index($Symbol, "_Z")==0)
13441 { # do not merge this
13442 if($PName1 eq "this" or $PName2 eq "this") {
13443 return;
13444 }
13445 }
13446
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013447 my %Type1 = get_Type($PType1_Id, 1);
13448 my %Type2 = get_Type($PType2_Id, 2);
13449 my %BaseType1 = get_BaseType($PType1_Id, 1);
13450 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013451 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013452
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013453 if($Level eq "Binary")
13454 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013455 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013456 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
13457 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
13458 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
13459 {
13460 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013461 "Target"=>$PName1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013462 "Param_Pos"=>$ParamPos1 );
13463 }
13464 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
13465 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
13466 {
13467 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013468 "Target"=>$PName1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013469 "Param_Pos"=>$ParamPos1 );
13470 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013471 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013472
13473 if(defined $UsedDump{1}{"DWARF"}
13474 and defined $UsedDump{2}{"DWARF"})
13475 {
13476 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
13477 {
13478 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
13479 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
13480 if($Old_Regs and $New_Regs)
13481 {
13482 if($Old_Regs ne $New_Regs)
13483 {
13484 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
13485 "Target"=>$PName1,
13486 "Param_Pos"=>$ParamPos1,
13487 "Old_Value"=>$Old_Regs,
13488 "New_Value"=>$New_Regs );
13489 }
13490 }
13491 elsif($Old_Regs and not $New_Regs)
13492 {
13493 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
13494 "Target"=>$PName1,
13495 "Param_Pos"=>$ParamPos1,
13496 "Old_Value"=>$Old_Regs );
13497 }
13498 elsif(not $Old_Regs and $New_Regs)
13499 {
13500 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
13501 "Target"=>$PName1,
13502 "Param_Pos"=>$ParamPos1,
13503 "New_Value"=>$New_Regs );
13504 }
13505 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
13506 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
13507 {
13508 if($Old_Offset ne $New_Offset)
13509 {
13510 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
13511 "Target"=>$PName1,
13512 "Param_Pos"=>$ParamPos1,
13513 "Old_Value"=>$Old_Offset,
13514 "New_Value"=>$New_Offset );
13515 }
13516 }
13517 }
13518 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013519 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013520 if(checkDump(1, "2.0") and checkDump(2, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013521 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013522 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
13523 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013524 if(not checkDump(1, "2.13")
13525 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013526 { # support for old ABI dumps
13527 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013528 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013529 if($Type1{"Name"} eq "bool"
13530 and $Value_Old eq "false" and $Value_New eq "0")
13531 { # int class::method ( bool p = 0 );
13532 # old ABI dumps: "false"
13533 # new ABI dumps: "0"
13534 $Value_Old = "0";
13535 }
13536 }
13537 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040013538 if(not checkDump(1, "2.18")
13539 and checkDump(2, "2.18"))
13540 { # support for old ABI dumps
13541 if(not defined $Value_Old
13542 and substr($Value_New, 0, 2) eq "_Z") {
13543 $Value_Old = $Value_New;
13544 }
13545 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013546 if(defined $Value_Old)
13547 {
13548 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
13549 if(defined $Value_New)
13550 {
13551 $Value_New = showVal($Value_New, $PType2_Id, 2);
13552 if($Value_Old ne $Value_New)
13553 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013554 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013555 "Target"=>$PName1,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013556 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013557 "Old_Value"=>$Value_Old,
13558 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013559 }
13560 }
13561 else
13562 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013563 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013564 "Target"=>$PName1,
13565 "Param_Pos"=>$ParamPos1,
13566 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013567 }
13568 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013569 elsif(defined $Value_New)
13570 {
13571 $Value_New = showVal($Value_New, $PType2_Id, 2);
13572 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
13573 "Target"=>$PName1,
13574 "Param_Pos"=>$ParamPos1,
13575 "New_Value"=>$Value_New );
13576 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013577 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013578
13579 if($ChkRnmd)
13580 {
13581 if($PName1 and $PName2 and $PName1 ne $PName2
13582 and $PType1_Id!=-1 and $PType2_Id!=-1
13583 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
13584 { # except unnamed "..." value list (Id=-1)
13585 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
13586 "Target"=>$PName1,
13587 "Param_Pos"=>$ParamPos1,
13588 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
13589 "Old_Value"=>$PName1,
13590 "New_Value"=>$PName2,
13591 "New_Signature"=>get_Signature($Symbol, 2) );
13592 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013593 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013594
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013595 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013596 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013597 foreach my $SubProblemType (keys(%SubProblems))
13598 { # add new problems, remove false alarms
13599 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13600 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013601
13602 # quals
13603 if($SubProblemType eq "Parameter_Type"
13604 or $SubProblemType eq "Parameter_Type_And_Size"
13605 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013606 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013607 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013608 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013609 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013610 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013611 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013612 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
13613 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
13614 }
13615 }
13616 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
13617 {
13618 if(removedQual($Old_Value, $New_Value, "volatile")) {
13619 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013620 }
13621 }
13622 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
13623 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
13624 { # int to "int const"
13625 delete($SubProblems{$SubProblemType});
13626 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013627 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013628 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
13629 { # "int const" to int
13630 delete($SubProblems{$SubProblemType});
13631 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013632 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
13633 { # "const" to non-"const"
13634 if($RR==2) {
13635 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
13636 }
13637 else {
13638 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
13639 }
13640 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013641 }
13642 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013643
13644 if($Level eq "Source")
13645 {
13646 foreach my $SubProblemType (keys(%SubProblems))
13647 {
13648 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13649 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
13650
13651 if($SubProblemType eq "Parameter_Type")
13652 {
13653 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13654 delete($SubProblems{$SubProblemType});
13655 }
13656 }
13657 }
13658 }
13659
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013660 foreach my $SubProblemType (keys(%SubProblems))
13661 { # modify/register problems
13662 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13663 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013664 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
13665 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013666
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013667 my $NewProblemType = $SubProblemType;
13668 if($Old_Value eq "..." and $New_Value ne "...")
13669 { # change from "..." to "int"
13670 if($ParamPos1==0)
13671 { # ISO C requires a named argument before "..."
13672 next;
13673 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013674 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013675 }
13676 elsif($New_Value eq "..." and $Old_Value ne "...")
13677 { # change from "int" to "..."
13678 if($ParamPos2==0)
13679 { # ISO C requires a named argument before "..."
13680 next;
13681 }
13682 $NewProblemType = "Parameter_Became_VaList";
13683 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013684 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013685 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013686 {
13687 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013688 if($Arch1 eq "unknown"
13689 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013690 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013691 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013692 ($Arch1, $Arch2) = ("unknown", "unknown");
13693 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013694 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013695 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013696 { # real
13697 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
13698 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
13699 }
13700 else
13701 { # model
13702 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13703 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13704 }
13705 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013706 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013707 if($Conv1{"Method"} eq "stack")
13708 {
13709 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
13710 $NewProblemType = "Parameter_Type_And_Stack";
13711 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013712 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013713 elsif($Conv1{"Method"} eq "reg")
13714 {
13715 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
13716 $NewProblemType = "Parameter_Type_And_Register";
13717 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013718 }
13719 }
13720 else
13721 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013722 if($Conv1{"Method"} eq "stack") {
13723 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013724 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013725 elsif($Conv1{"Method"} eq "register") {
13726 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013727 }
13728 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013729 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
13730 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013731 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013732 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013733 "Target"=>$PName1,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013734 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013735 "New_Signature"=>get_Signature($Symbol, 2) );
13736 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013737 }
13738 @RecurTypes = ();
13739 # checking type definition changes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013740 my %SubProblems_Merge = mergeTypes($PType1_Id, $PType2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013741 foreach my $SubProblemType (keys(%SubProblems_Merge))
13742 {
13743 foreach my $SubLocation (keys(%{$SubProblems_Merge{$SubProblemType}}))
13744 {
13745 my $NewProblemType = $SubProblemType;
13746 if($SubProblemType eq "DataType_Size")
13747 {
13748 my $InitialType_Type = $SubProblems_Merge{$SubProblemType}{$SubLocation}{"InitialType_Type"};
13749 if($InitialType_Type!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
13750 { # stack has been affected
13751 $NewProblemType = "DataType_Size_And_Stack";
13752 }
13753 }
13754 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013755 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013756 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013757 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013758 "Param_Name"=>$PName1 );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013759 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}}{keys(%{$SubProblems_Merge{$SubProblemType}{$SubLocation}})} = values %{$SubProblems_Merge{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013760 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013761 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$PType1_Id}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013762 }
13763 }
13764 }
13765}
13766
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013767sub find_ParamPair_Pos_byName($$$)
13768{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013769 my ($Name, $Symbol, $LibVersion) = @_;
13770 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013771 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013772 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
13773 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013774 {
13775 return $ParamPos;
13776 }
13777 }
13778 return "lost";
13779}
13780
13781sub find_ParamPair_Pos_byTypeAndPos($$$$$)
13782{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013783 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013784 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013785 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013786 {
13787 next if($Order eq "backward" and $ParamPos>$MediumPos);
13788 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013789 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
13790 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013791 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013792 push(@Positions, $ParamPos);
13793 }
13794 }
13795 return @Positions;
13796}
13797
13798sub getTypeIdByName($$)
13799{
13800 my ($TypeName, $Version) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013801 return $TName_Tid{$Version}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013802}
13803
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013804sub diffTypes($$$)
13805{
13806 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
13807 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
13808 }
13809 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
13810 { # skip recursive declarations
13811 return 0;
13812 }
13813
13814 pushType($_[0], $_[1], \@RecurTypes_Diff);
13815 my $Diff = diffTypes_I(@_);
13816 pop(@RecurTypes_Diff);
13817
13818 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
13819}
13820
13821sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013822{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013823 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013824
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013825 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
13826 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013827
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013828 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
13829 { # equal types
13830 return 0;
13831 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013832 if($Type1_Pure{"Name"} eq "void")
13833 { # from void* to something
13834 return 0;
13835 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013836 if($Type1_Pure{"Name"}=~/\*/
13837 or $Type2_Pure{"Name"}=~/\*/)
13838 { # compared in detectTypeChange()
13839 return 0;
13840 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013841
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013842 my %FloatType = map {$_=>1} (
13843 "float",
13844 "double",
13845 "long double"
13846 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013847
13848 my $T1 = $Type1_Pure{"Type"};
13849 my $T2 = $Type2_Pure{"Type"};
13850
13851 if($T1 eq "Struct"
13852 and $T2 eq "Class")
13853 { # compare as data structures
13854 $T2 = "Struct";
13855 }
13856
13857 if($T1 eq "Class"
13858 and $T2 eq "Struct")
13859 { # compare as data structures
13860 $T1 = "Struct";
13861 }
13862
13863 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013864 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013865 if($T1 eq "Intrinsic"
13866 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013867 { # "int" to "enum"
13868 return 0;
13869 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013870 elsif($T2 eq "Intrinsic"
13871 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013872 { # "enum" to "int"
13873 return 0;
13874 }
13875 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013876 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013877 # ...
13878 return 1;
13879 }
13880 }
13881 else
13882 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013883 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013884 {
13885 if($FloatType{$Type1_Pure{"Name"}}
13886 or $FloatType{$Type2_Pure{"Name"}})
13887 { # "float" to "double"
13888 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013889 if($Level eq "Source")
13890 { # Safe
13891 return 0;
13892 }
13893 else {
13894 return 1;
13895 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013896 }
13897 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013898 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013899 {
13900 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
13901 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013902 if(not @Membs1
13903 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013904 { # private
13905 return 0;
13906 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013907 if($#Membs1!=$#Membs2)
13908 { # different number of elements
13909 return 1;
13910 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013911 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013912 {
13913 foreach my $Pos (@Membs1)
13914 { # compare elements by name and value
13915 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
13916 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
13917 { # different names
13918 return 1;
13919 }
13920 }
13921 }
13922 else
13923 {
13924 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013925 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013926 if($Level eq "Source")
13927 {
13928 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
13929 { # different names
13930 return 1;
13931 }
13932 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013933
13934 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
13935 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
13936
13937 if($MT1{"Name"} ne $MT2{"Name"}
13938 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
13939 {
13940 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
13941 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
13942
13943 if($PL1 ne $PL2)
13944 { # different pointer level
13945 return 1;
13946 }
13947
13948 # compare base types
13949 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
13950 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
13951
13952 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
13953 { # different types
13954 return 1;
13955 }
13956 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013957 }
13958 }
13959 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013960 else
13961 {
13962 # TODO: arrays, etc.
13963 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013964 }
13965 return 0;
13966}
13967
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013968sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013969{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013970 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013971 if(not $Type1_Id or not $Type2_Id) {
13972 return ();
13973 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013974 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013975 my %Type1 = get_Type($Type1_Id, 1);
13976 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013977 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
13978 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
13979 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
13980 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 +040013981
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013982 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
13983 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013984 return () if(not $Type1{"Name"} or not $Type2{"Name"});
13985 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
13986 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
13987 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
13988 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
13989 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
13990 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013991 if($Type1{"Name"} eq $Type2{"Name"})
13992 {
13993 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
13994 { # will be reported in mergeTypes() as typedef problem
13995 return ();
13996 }
13997 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
13998 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
13999 if(%Typedef_1 and %Typedef_2)
14000 {
14001 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14002 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14003 { # const Typedef
14004 return ();
14005 }
14006 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014007 }
14008 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14009 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014010 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014011 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14012 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014013 {
14014 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14015 "Old_Value"=>$Type1_Base{"Name"},
14016 "New_Value"=>$Type2_Base{"Name"},
14017 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
14018 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
14019 "InitialType_Type"=>$Type1_Pure{"Type"});
14020 }
14021 else
14022 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014023 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014024 { # format change
14025 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14026 "Old_Value"=>$Type1_Base{"Name"},
14027 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014028 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
14029 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014030 "InitialType_Type"=>$Type1_Pure{"Type"});
14031 }
14032 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14033 {
14034 %{$LocalProblems{$Prefix."_BaseType"}}=(
14035 "Old_Value"=>$Type1_Base{"Name"},
14036 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014037 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
14038 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014039 "InitialType_Type"=>$Type1_Pure{"Type"});
14040 }
14041 }
14042 }
14043 }
14044 elsif($Type1{"Name"} ne $Type2{"Name"})
14045 { # type change
14046 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14047 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014048 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014049 and $Type1_Pure{"Name"} eq "void")
14050 {
14051 %{$LocalProblems{"Return_Type_From_Void"}}=(
14052 "New_Value"=>$Type2{"Name"},
14053 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
14054 "InitialType_Type"=>$Type1_Pure{"Type"});
14055 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014056 elsif($Prefix eq "Return"
14057 and $Type2_Pure{"Name"} eq "void")
14058 {
14059 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14060 "Old_Value"=>$Type1{"Name"},
14061 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14062 "InitialType_Type"=>$Type1_Pure{"Type"});
14063 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014064 else
14065 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014066 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014067 and $Type1{"Size"} and $Type2{"Size"}
14068 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014069 {
14070 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14071 "Old_Value"=>$Type1{"Name"},
14072 "New_Value"=>$Type2{"Name"},
14073 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14074 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
14075 "InitialType_Type"=>$Type1_Pure{"Type"});
14076 }
14077 else
14078 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014079 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014080 { # format change
14081 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14082 "Old_Value"=>$Type1{"Name"},
14083 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014084 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14085 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014086 "InitialType_Type"=>$Type1_Pure{"Type"});
14087 }
14088 elsif(tNameLock($Type1_Id, $Type2_Id))
14089 { # FIXME: correct this condition
14090 %{$LocalProblems{$Prefix."_Type"}}=(
14091 "Old_Value"=>$Type1{"Name"},
14092 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014093 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14094 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014095 "InitialType_Type"=>$Type1_Pure{"Type"});
14096 }
14097 }
14098 }
14099 }
14100 }
14101 if($Type1_PLevel!=$Type2_PLevel)
14102 {
14103 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14104 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14105 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014106 if($Level eq "Source")
14107 {
14108 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014109 "Old_Value"=>$Type1_PLevel,
14110 "New_Value"=>$Type2_PLevel);
14111 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014112 else
14113 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014114 if($Type2_PLevel>$Type1_PLevel)
14115 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014116 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14117 "Old_Value"=>$Type1_PLevel,
14118 "New_Value"=>$Type2_PLevel);
14119 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014120 else
14121 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014122 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14123 "Old_Value"=>$Type1_PLevel,
14124 "New_Value"=>$Type2_PLevel);
14125 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014126 }
14127 }
14128 }
14129 if($Type1_Pure{"Type"} eq "Array")
14130 { # base_type[N] -> base_type[N]
14131 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014132 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014133 foreach my $SubProblemType (keys(%SubProblems))
14134 {
14135 $SubProblemType=~s/_Type/_BaseType/g;
14136 next if(defined $LocalProblems{$SubProblemType});
14137 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14138 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14139 }
14140 }
14141 }
14142 return %LocalProblems;
14143}
14144
14145sub tNameLock($$)
14146{
14147 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014148 my $Changed = 0;
14149 if(differentDumps("G"))
14150 { # different GCC versions
14151 $Changed = 1;
14152 }
14153 elsif(differentDumps("V"))
14154 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014155 if(not checkDump(1, "2.20")
14156 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014157 { # latest names update
14158 # 2.6: added restrict qualifier
14159 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014160 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014161 $Changed = 1;
14162 }
14163 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014164
14165 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14166 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14167
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014168 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014169 { # different formats
14170 if($UseOldDumps)
14171 { # old dumps
14172 return 0;
14173 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014174
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014175 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14176 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014177
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014178 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014179 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014180 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014181 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014182 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014183 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014184 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014185 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014186 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14187 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14188 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014189 { # equal base types
14190 return 0;
14191 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014192
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014193 if(not checkDump(1, "2.13")
14194 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014195 { # broken array names in ABI dumps < 2.13
14196 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014197 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014198 return 0;
14199 }
14200 }
14201
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014202 if(not checkDump(1, "2.6")
14203 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014204 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014205 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014206 and $TN2=~/\brestrict\b/) {
14207 return 0;
14208 }
14209 }
14210
14211 if(not checkDump(1, "2.20")
14212 or not checkDump(2, "2.20"))
14213 { # added restrict attribute in 2.6
14214 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14215 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014216 return 0;
14217 }
14218 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014219 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014220 else
14221 {
14222 # typedef struct {...} type_t
14223 # typedef struct type_t {...} type_t
14224 if(index($TN1, " ".$TN2)!=-1)
14225 {
14226 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
14227 return 0;
14228 }
14229 }
14230 if(index($TN2, " ".$TN1)!=-1)
14231 {
14232 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
14233 return 0;
14234 }
14235 }
14236 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014237 return 1;
14238}
14239
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014240sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014241{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014242 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014243 if(defined $Cache{"differentDumps"}{$Check}) {
14244 return $Cache{"differentDumps"}{$Check};
14245 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014246 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014247 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014248 if($Check eq "G")
14249 {
14250 if(getGccVersion(1) ne getGccVersion(2))
14251 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014252 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014253 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014254 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014255 if($Check eq "V")
14256 {
14257 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
14258 formatVersion($UsedDump{2}{"V"}, 2))!=0)
14259 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014260 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014261 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014262 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014263 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014264 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014265}
14266
14267sub formatVersion($$)
14268{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014269 my ($V, $Digits) = @_;
14270 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014271 return join(".", splice(@Elems, 0, $Digits));
14272}
14273
14274sub htmlSpecChars($)
14275{
14276 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014277 if(not $Str) {
14278 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014279 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014280 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14281 $Str=~s/</&lt;/g;
14282 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
14283 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014284 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
14285 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014286 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014287 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014288 $Str=~s/\n/<br\/>/g;
14289 $Str=~s/\"/&quot;/g;
14290 $Str=~s/\'/&#39;/g;
14291 return $Str;
14292}
14293
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014294sub xmlSpecChars($)
14295{
14296 my $Str = $_[0];
14297 if(not $Str) {
14298 return $Str;
14299 }
14300
14301 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14302 $Str=~s/</&lt;/g;
14303 $Str=~s/>/&gt;/g;
14304
14305 $Str=~s/\"/&quot;/g;
14306 $Str=~s/\'/&#39;/g;
14307
14308 return $Str;
14309}
14310
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014311sub xmlSpecChars_R($)
14312{
14313 my $Str = $_[0];
14314 if(not $Str) {
14315 return $Str;
14316 }
14317
14318 $Str=~s/&amp;/&/g;
14319 $Str=~s/&lt;/</g;
14320 $Str=~s/&gt;/>/g;
14321
14322 $Str=~s/&quot;/"/g;
14323 $Str=~s/&#39;/'/g;
14324
14325 return $Str;
14326}
14327
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014328sub black_name($)
14329{
14330 my $Name = $_[0];
14331 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
14332}
14333
14334sub highLight_Signature($)
14335{
14336 my $Signature = $_[0];
14337 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
14338}
14339
14340sub highLight_Signature_Italic_Color($)
14341{
14342 my $Signature = $_[0];
14343 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
14344}
14345
14346sub separate_symbol($)
14347{
14348 my $Symbol = $_[0];
14349 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
14350 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
14351 ($Name, $Spec, $Ver) = ($1, $2, $3);
14352 }
14353 return ($Name, $Spec, $Ver);
14354}
14355
14356sub cut_f_attrs($)
14357{
14358 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
14359 return $2;
14360 }
14361 return "";
14362}
14363
14364sub highLight_Signature_PPos_Italic($$$$$)
14365{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014366 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
14367 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014368 if($CheckObjectsOnly) {
14369 $ItalicParams=$ColorParams=0;
14370 }
14371 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
14372 my $Return = "";
14373 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
14374 $Return = $2;
14375 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014376 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014377 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014378 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014379 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014380 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014381 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014382 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014383 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014384 }
14385 return $Signature;
14386 }
14387 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
14388 $Begin.=" " if($Begin!~/ \Z/);
14389 $End = cut_f_attrs($Signature);
14390 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014391 my ($Short, $Params) = split_Signature($Signature);
14392 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014393 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014394 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014395 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014396 $Part=~s/\A\s+|\s+\Z//g;
14397 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
14398 if($Part=~/\([\*]+(\w+)\)/i) {
14399 $ParamName = $1;#func-ptr
14400 }
14401 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
14402 $ParamName = $1;
14403 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014404 if(not $ParamName)
14405 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014406 push(@Parts, $Part_Styled);
14407 next;
14408 }
14409 if($ItalicParams and not $TName_Tid{1}{$Part}
14410 and not $TName_Tid{2}{$Part})
14411 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014412 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014413 if($Param_Pos ne ""
14414 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014415 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014416 }
14417 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014418 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014419 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014420 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014421 }
14422 $Part_Styled=~s/,(\w)/, $1/g;
14423 push(@Parts, $Part_Styled);
14424 }
14425 if(@Parts)
14426 {
14427 foreach my $Num (0 .. $#Parts)
14428 {
14429 if($Num==$#Parts)
14430 { # add ")" to the last parameter
14431 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
14432 }
14433 elsif(length($Parts[$Num])<=45) {
14434 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
14435 }
14436 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014437 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014438 }
14439 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014440 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014441 }
14442 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014443 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014444 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014445 $Signature=~s!\[\]![&#160;]!g;
14446 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014447 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
14448 if($SymbolVersion) {
14449 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
14450 }
14451 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014452}
14453
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014454sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014455{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014456 my $Signature = $_[0];
14457 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
14458 {
14459 $Signature=~s/\A\Q$ShortName\E\(//g;
14460 cut_f_attrs($Signature);
14461 $Signature=~s/\)\Z//;
14462 return ($ShortName, $Signature);
14463 }
14464
14465 # error
14466 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014467}
14468
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014469sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014470{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014471 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014472 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014473 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
14474 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014475 foreach my $Pos (0 .. length($Params) - 1)
14476 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014477 my $S = substr($Params, $Pos, 1);
14478 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014479 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014480 }
14481 if($S eq "," and
14482 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014483 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014484 if($Comma)
14485 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014486 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014487 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014488 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014489 }
14490 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014491 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014492 }
14493 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014494 if(not $Sp)
14495 { # remove spaces
14496 foreach (@Parts)
14497 {
14498 s/\A //g;
14499 s/ \Z//g;
14500 }
14501 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014502 return @Parts;
14503}
14504
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014505sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014506{
14507 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014508 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014509 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014510 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
14511 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014512 $Center+=length($1);
14513 }
14514 foreach my $Pos (0 .. length($Sign)-1)
14515 {
14516 my $S = substr($Sign, $Pos, 1);
14517 if($S eq $Target)
14518 {
14519 if($B{"("}==$B{")"}
14520 and $B{"<"}==$B{">"}) {
14521 return $Center;
14522 }
14523 }
14524 if(defined $B{$S}) {
14525 $B{$S}+=1;
14526 }
14527 $Center+=1;
14528 }
14529 return 0;
14530}
14531
14532sub appendFile($$)
14533{
14534 my ($Path, $Content) = @_;
14535 return if(not $Path);
14536 if(my $Dir = get_dirname($Path)) {
14537 mkpath($Dir);
14538 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014539 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014540 print FILE $Content;
14541 close(FILE);
14542}
14543
14544sub writeFile($$)
14545{
14546 my ($Path, $Content) = @_;
14547 return if(not $Path);
14548 if(my $Dir = get_dirname($Path)) {
14549 mkpath($Dir);
14550 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014551 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014552 print FILE $Content;
14553 close(FILE);
14554}
14555
14556sub readFile($)
14557{
14558 my $Path = $_[0];
14559 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014560 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014561 local $/ = undef;
14562 my $Content = <FILE>;
14563 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014564 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014565 $Content=~s/\r/\n/g;
14566 }
14567 return $Content;
14568}
14569
14570sub get_filename($)
14571{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014572 if(defined $Cache{"get_filename"}{$_[0]}) {
14573 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014574 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014575 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
14576 return ($Cache{"get_filename"}{$_[0]}=$1);
14577 }
14578 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014579}
14580
14581sub get_dirname($)
14582{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014583 if(defined $Cache{"get_dirname"}{$_[0]}) {
14584 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014585 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014586 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
14587 return ($Cache{"get_dirname"}{$_[0]}=$1);
14588 }
14589 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014590}
14591
14592sub separate_path($) {
14593 return (get_dirname($_[0]), get_filename($_[0]));
14594}
14595
14596sub esc($)
14597{
14598 my $Str = $_[0];
14599 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
14600 return $Str;
14601}
14602
14603sub readLineNum($$)
14604{
14605 my ($Path, $Num) = @_;
14606 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014607 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014608 foreach (1 ... $Num) {
14609 <FILE>;
14610 }
14611 my $Line = <FILE>;
14612 close(FILE);
14613 return $Line;
14614}
14615
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014616sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014617{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014618 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014619 return () if(not $Path or not -f $Path);
14620 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014621 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
14622 {
14623 foreach my $AttrVal (split(/;/, $1))
14624 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014625 if($AttrVal=~/(.+):(.+)/)
14626 {
14627 my ($Name, $Value) = ($1, $2);
14628 $Attributes{$Name} = $Value;
14629 }
14630 }
14631 }
14632 return \%Attributes;
14633}
14634
14635sub is_abs($) {
14636 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
14637}
14638
14639sub get_abs_path($)
14640{ # abs_path() should NOT be called for absolute inputs
14641 # because it can change them
14642 my $Path = $_[0];
14643 if(not is_abs($Path)) {
14644 $Path = abs_path($Path);
14645 }
14646 return $Path;
14647}
14648
14649sub get_OSgroup()
14650{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014651 my $N = $Config{"osname"};
14652 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014653 return "macos";
14654 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014655 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014656 return "bsd";
14657 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014658 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014659 return "beos";
14660 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014661 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014662 return "symbian";
14663 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014664 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014665 return "windows";
14666 }
14667 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014668 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014669 }
14670}
14671
14672sub getGccVersion($)
14673{
14674 my $LibVersion = $_[0];
14675 if($GCC_VERSION{$LibVersion})
14676 { # dump version
14677 return $GCC_VERSION{$LibVersion};
14678 }
14679 elsif($UsedDump{$LibVersion}{"V"})
14680 { # old-version dumps
14681 return "unknown";
14682 }
14683 my $GccVersion = get_dumpversion($GCC_PATH); # host version
14684 if(not $GccVersion) {
14685 return "unknown";
14686 }
14687 return $GccVersion;
14688}
14689
14690sub showArch($)
14691{
14692 my $Arch = $_[0];
14693 if($Arch eq "arm"
14694 or $Arch eq "mips") {
14695 return uc($Arch);
14696 }
14697 return $Arch;
14698}
14699
14700sub getArch($)
14701{
14702 my $LibVersion = $_[0];
14703 if($CPU_ARCH{$LibVersion})
14704 { # dump version
14705 return $CPU_ARCH{$LibVersion};
14706 }
14707 elsif($UsedDump{$LibVersion}{"V"})
14708 { # old-version dumps
14709 return "unknown";
14710 }
14711 if(defined $Cache{"getArch"}{$LibVersion}) {
14712 return $Cache{"getArch"}{$LibVersion};
14713 }
14714 my $Arch = get_dumpmachine($GCC_PATH); # host version
14715 if(not $Arch) {
14716 return "unknown";
14717 }
14718 if($Arch=~/\A([\w]{3,})(-|\Z)/) {
14719 $Arch = $1;
14720 }
14721 $Arch = "x86" if($Arch=~/\Ai[3-7]86\Z/);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040014722 if($OSgroup eq "windows")
14723 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014724 $Arch = "x86" if($Arch=~/win32|mingw32/i);
14725 $Arch = "x86_64" if($Arch=~/win64|mingw64/i);
14726 }
14727 $Cache{"getArch"}{$LibVersion} = $Arch;
14728 return $Arch;
14729}
14730
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014731sub get_Report_Header($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014732{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014733 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014734 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014735 if(getArch(1) ne getArch(2)
14736 or getArch(1) eq "unknown"
14737 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014738 { # don't show architecture in the header
14739 $ArchInfo="";
14740 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014741 my $Report_Header = "<h1><span class='nowrap'>";
14742 if($Level eq "Source") {
14743 $Report_Header .= "Source compatibility";
14744 }
14745 elsif($Level eq "Binary") {
14746 $Report_Header .= "Binary compatibility";
14747 }
14748 else {
14749 $Report_Header .= "API compatibility";
14750 }
14751 $Report_Header .= " report for the <span style='color:Blue;'>$TargetLibraryFName</span> $TargetComponent</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014752 $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>";
14753 if($AppPath) {
14754 $Report_Header .= " <span class='nowrap'>&#160;(relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)</span>";
14755 }
14756 $Report_Header .= "</h1>\n";
14757 return $Report_Header;
14758}
14759
14760sub get_SourceInfo()
14761{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014762 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014763 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014764 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014765 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014766 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014767 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
14768 $CheckedHeaders .= "<div class='h_list'>\n";
14769 foreach my $Header_Path (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
14770 {
14771 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
14772 my $Name = get_filename($Identity);
14773 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
14774 $CheckedHeaders .= $Name.$Comment."<br/>\n";
14775 }
14776 $CheckedHeaders .= "</div>\n";
14777 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014778 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014779
14780 if(my @Sources = keys(%{$Registered_Sources{1}}))
14781 {
14782 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
14783 $CheckedSources .= "<div class='h_list'>\n";
14784 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
14785 {
14786 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
14787 my $Name = get_filename($Identity);
14788 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
14789 $CheckedSources .= $Name.$Comment."<br/>\n";
14790 }
14791 $CheckedSources .= "</div>\n";
14792 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
14793 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014794 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014795 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014796 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014797 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014798 $CheckedLibs .= "<div class='lib_list'>\n";
14799 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
14800 {
14801 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
14802 $CheckedLibs .= $Library."<br/>\n";
14803 }
14804 $CheckedLibs .= "</div>\n";
14805 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014806 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014807 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
14808}
14809
14810sub get_ObjTitle()
14811{
14812 if(defined $UsedDump{1}{"DWARF"}) {
14813 return "Objects";
14814 }
14815 else {
14816 return ucfirst($SLIB_TYPE)." Libraries";
14817 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014818}
14819
14820sub get_TypeProblems_Count($$$)
14821{
14822 my ($TypeChanges, $TargetPriority, $Level) = @_;
14823 my $Type_Problems_Count = 0;
14824 foreach my $Type_Name (sort keys(%{$TypeChanges}))
14825 {
14826 my %Kinds_Target = ();
14827 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
14828 {
14829 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
14830 {
14831 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
14832 my $Priority = getProblemSeverity($Level, $Kind);
14833 next if($Priority ne $TargetPriority);
14834 if($Kinds_Target{$Kind}{$Target}) {
14835 next;
14836 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014837 if(cmpSeverities($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014838 { # select a problem with the highest priority
14839 next;
14840 }
14841 $Kinds_Target{$Kind}{$Target} = 1;
14842 $Type_Problems_Count += 1;
14843 }
14844 }
14845 }
14846 return $Type_Problems_Count;
14847}
14848
14849sub get_Summary($)
14850{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014851 my $Level = $_[0];
14852 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014853 $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 +040014854 %{$RESULT{$Level}} = (
14855 "Problems"=>0,
14856 "Warnings"=>0,
14857 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014858 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014859 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014860 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014861 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014862 {
14863 if(not defined $CompatRules{$Level}{$Kind})
14864 { # unknown rule
14865 if(not $UnknownRules{$Level}{$Kind})
14866 { # only one warning
14867 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
14868 $UnknownRules{$Level}{$Kind}=1;
14869 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014870 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014871 }
14872 }
14873 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014874 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
14875 {
14876 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
14877 {
14878 if(not defined $CompatRules{$Level}{$Kind})
14879 { # unknown rule
14880 if(not $UnknownRules{$Level}{$Kind})
14881 { # only one warning
14882 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
14883 $UnknownRules{$Level}{$Kind}=1;
14884 }
14885 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
14886 }
14887 }
14888 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014889 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014890 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014891 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014892 {
14893 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
14894 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014895 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014896 {
14897 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014898 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014899 $Added += 1;
14900 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014901 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014902 {
14903 $Removed += 1;
14904 $TotalAffected{$Level}{$Interface} = $Priority;
14905 }
14906 else
14907 {
14908 if($Priority eq "Safe") {
14909 $I_Other += 1;
14910 }
14911 elsif($Priority eq "High") {
14912 $I_Problems_High += 1;
14913 }
14914 elsif($Priority eq "Medium") {
14915 $I_Problems_Medium += 1;
14916 }
14917 elsif($Priority eq "Low") {
14918 $I_Problems_Low += 1;
14919 }
14920 if(($Priority ne "Low" or $StrictCompat)
14921 and $Priority ne "Safe") {
14922 $TotalAffected{$Level}{$Interface} = $Priority;
14923 }
14924 }
14925 }
14926 }
14927 }
14928 }
14929 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014930 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014931 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014932 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014933 {
14934 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
14935 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014936 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014937 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014938 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
14939 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014940 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014941 if(cmpSeverities($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014942 { # select a problem with the highest priority
14943 next;
14944 }
14945 if(($Priority ne "Low" or $StrictCompat)
14946 and $Priority ne "Safe") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014947 $TotalAffected{$Level}{$Interface} = maxSeverity($TotalAffected{$Level}{$Interface}, $Priority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014948 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014949 %{$TypeChanges{$Type_Name}{$Kind}{$Location}} = %{$CompatProblems{$Level}{$Interface}{$Kind}{$Location}};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014950 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = maxSeverity($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014951 }
14952 }
14953 }
14954 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014955
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014956 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
14957 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
14958 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
14959 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014960
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014961 if($CheckObjectsOnly)
14962 { # only removed exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014963 $RESULT{$Level}{"Affected"} = $Removed*100/keys(%{$Symbol_Library{1}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014964 }
14965 else
14966 { # changed and removed public symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014967 my $SCount = keys(%{$CheckedSymbols{$Level}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014968 if($ExtendedCheck)
14969 { # don't count external_func_0 for constants
14970 $SCount-=1;
14971 }
14972 if($SCount)
14973 {
14974 my %Weight = (
14975 "High" => 100,
14976 "Medium" => 50,
14977 "Low" => 25
14978 );
14979 foreach (keys(%{$TotalAffected{$Level}})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014980 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014981 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014982 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014983 }
14984 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014985 $RESULT{$Level}{"Affected"} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014986 }
14987 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014988 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
14989 if($RESULT{$Level}{"Affected"}>=100) {
14990 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014991 }
14992
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014993 $RESULT{$Level}{"Problems"} += $Removed;
14994 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014995 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014996 if($StrictCompat) {
14997 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
14998 }
14999 else {
15000 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15001 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015002
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015003 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015004 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015005 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015006 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015007 my $Severity = getProblemSeverity($Level, $Kind);
15008 if($Severity eq "Safe")
15009 {
15010 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015011 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015012 elsif($Severity eq "Low")
15013 {
15014 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015015 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015016 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015017 }
15018
15019 if($C_Problems_Low)
15020 {
15021 if($StrictCompat) {
15022 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15023 }
15024 else {
15025 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015026 }
15027 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015028 if($CheckImpl and $Level eq "Binary")
15029 {
15030 if($StrictCompat) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015031 $RESULT{$Level}{"Problems"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015032 }
15033 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015034 $RESULT{$Level}{"Warnings"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015035 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015036 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015037 if($RESULT{$Level}{"Problems"}
15038 and $RESULT{$Level}{"Affected"}) {
15039 $RESULT{$Level}{"Verdict"} = "incompatible";
15040 }
15041 else {
15042 $RESULT{$Level}{"Verdict"} = "compatible";
15043 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015044
15045 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15046 if(not $TotalTypes)
15047 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015048 $TotalTypes = keys(%{$TName_Tid{1}});
15049 }
15050
15051 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15052 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15053
15054 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15055
15056 if($ReportFormat eq "xml")
15057 { # XML
15058 # test info
15059 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15060 $TestInfo .= " <version1>\n";
15061 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
15062 $TestInfo .= " <architecture>$Arch1</architecture>\n";
15063 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15064 $TestInfo .= " </version1>\n";
15065
15066 $TestInfo .= " <version2>\n";
15067 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
15068 $TestInfo .= " <architecture>$Arch2</architecture>\n";
15069 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15070 $TestInfo .= " </version2>\n";
15071 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15072
15073 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015074 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015075 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015076 $TestResults .= " <headers>\n";
15077 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15078 {
15079 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15080 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15081 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15082 }
15083 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015084 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015085
15086 if(my @Sources = keys(%{$Registered_Sources{1}}))
15087 {
15088 $TestResults .= " <sources>\n";
15089 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15090 {
15091 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15092 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15093 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15094 }
15095 $TestResults .= " </sources>\n";
15096 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015097
15098 $TestResults .= " <libs>\n";
15099 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15100 {
15101 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15102 $TestResults .= " <name>$Library</name>\n";
15103 }
15104 $TestResults .= " </libs>\n";
15105
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015106 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015107 $TestResults .= " <types>".$TotalTypes."</types>\n";
15108
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015109 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15110 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015111 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15112
15113 # problem summary
15114 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15115 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15116
15117 $Problem_Summary .= " <problems_with_types>\n";
15118 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15119 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15120 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15121 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15122 $Problem_Summary .= " </problems_with_types>\n";
15123
15124 $Problem_Summary .= " <problems_with_symbols>\n";
15125 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15126 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15127 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015128 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015129 $Problem_Summary .= " </problems_with_symbols>\n";
15130
15131 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015132 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015133 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015134 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015135 {
15136 $Problem_Summary .= " <impl>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015137 $Problem_Summary .= " <low>".keys(%CompatProblems_Impl)."</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015138 $Problem_Summary .= " </impl>\n";
15139 }
15140 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15141
15142 return ($TestInfo.$TestResults.$Problem_Summary, "");
15143 }
15144 else
15145 { # HTML
15146 # test info
15147 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015148 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015149 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetLibraryFName</td></tr>\n";
15150
15151 my (@VInf1, @VInf2, $AddTestInfo) = ();
15152 if($Arch1 ne "unknown"
15153 and $Arch2 ne "unknown")
15154 { # CPU arch
15155 if($Arch1 eq $Arch2)
15156 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015157 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015158 }
15159 else
15160 { # go to the version number
15161 push(@VInf1, showArch($Arch1));
15162 push(@VInf2, showArch($Arch2));
15163 }
15164 }
15165 if($GccV1 ne "unknown"
15166 and $GccV2 ne "unknown"
15167 and $OStarget ne "windows")
15168 { # GCC version
15169 if($GccV1 eq $GccV2)
15170 { # go to the separate section
15171 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15172 }
15173 else
15174 { # go to the version number
15175 push(@VInf1, "gcc ".$GccV1);
15176 push(@VInf2, "gcc ".$GccV2);
15177 }
15178 }
15179 # show long version names with GCC version and CPU architecture name (if different)
15180 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
15181 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
15182 $TestInfo .= $AddTestInfo;
15183 #if($COMMON_LANGUAGE{1}) {
15184 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
15185 #}
15186 if($ExtendedCheck) {
15187 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
15188 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015189 if($JoinReport)
15190 {
15191 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015192 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015193 }
15194 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015195 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015196 }
15197 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015198 $TestInfo .= "</table>\n";
15199
15200 # test results
15201 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015202 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015203
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015204 if(my @Headers = keys(%{$Registered_Headers{1}}))
15205 {
15206 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
15207 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
15208 }
15209 elsif($CheckObjectsOnly) {
15210 $TestResults .= "<tr><th>Total Header Files</th><td>0&#160;(not&#160;analyzed)</td></tr>\n";
15211 }
15212
15213 if(my @Sources = keys(%{$Registered_Sources{1}}))
15214 {
15215 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
15216 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
15217 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015218
15219 if(not $ExtendedCheck)
15220 {
15221 my $Libs_Link = "0";
15222 $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 +040015223 $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 +040015224 }
15225
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015226 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015227
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015228 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015229 if($JoinReport) {
15230 $META_DATA = "kind:".lc($Level).";".$META_DATA;
15231 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015232 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015233 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015234 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
15235 }
15236 else {
15237 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
15238 }
15239 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015240 $TestResults .= "</table>\n";
15241
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015242 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015243 # problem summary
15244 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015245 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015246 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
15247
15248 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015249 if($Added>0)
15250 {
15251 if($JoinReport) {
15252 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
15253 }
15254 else {
15255 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
15256 }
15257 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015258 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015259 $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 +040015260
15261 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015262 if($Removed>0)
15263 {
15264 if($JoinReport) {
15265 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
15266 }
15267 else {
15268 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
15269 }
15270 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015271 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015272 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
15273 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015274
15275 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015276 $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 +040015277 $TH_Link = "n/a" if($CheckObjectsOnly);
15278 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015279 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
15280 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015281
15282 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015283 $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 +040015284 $TM_Link = "n/a" if($CheckObjectsOnly);
15285 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015286 $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 +040015287
15288 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015289 $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 +040015290 $TL_Link = "n/a" if($CheckObjectsOnly);
15291 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015292 $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 +040015293
15294 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015295 $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 +040015296 $IH_Link = "n/a" if($CheckObjectsOnly);
15297 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015298 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
15299 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015300
15301 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015302 $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 +040015303 $IM_Link = "n/a" if($CheckObjectsOnly);
15304 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015305 $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 +040015306
15307 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015308 $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 +040015309 $IL_Link = "n/a" if($CheckObjectsOnly);
15310 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015311 $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 +040015312
15313 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015314 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
15315 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015316 }
15317 $ChangedConstants_Link = "n/a" if($CheckObjectsOnly);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015318 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015319 $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 +040015320
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015321 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015322 {
15323 my $ChangedImpl_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015324 $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 +040015325 $ChangedImpl_Link = "n/a" if($CheckHeadersOnly);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015326 $META_DATA .= "changed_implementation:".keys(%CompatProblems_Impl).";";
15327 $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 +040015328 }
15329 # Safe Changes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015330 if($T_Other and not $CheckObjectsOnly)
15331 {
15332 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015333 $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 +040015334 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015335
15336 if($I_Other and not $CheckObjectsOnly)
15337 {
15338 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015339 $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 +040015340 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015341
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015342 if($C_Other and not $CheckObjectsOnly)
15343 {
15344 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
15345 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
15346 }
15347
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015348 $META_DATA .= "tool_version:$TOOL_VERSION";
15349 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015350 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015351 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
15352 }
15353}
15354
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015355sub getStyle($$$)
15356{
15357 my ($Subj, $Act, $Num) = @_;
15358 my %Style = (
15359 "A"=>"new",
15360 "R"=>"failed",
15361 "S"=>"passed",
15362 "L"=>"warning",
15363 "M"=>"failed",
15364 "H"=>"failed"
15365 );
15366 if($Num>0) {
15367 return " class='".$Style{$Act}."'";
15368 }
15369 return "";
15370}
15371
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015372sub show_number($)
15373{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015374 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015375 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015376 my $Num = cut_off_number($_[0], 2, 0);
15377 if($Num eq "0")
15378 {
15379 foreach my $P (3 .. 7)
15380 {
15381 $Num = cut_off_number($_[0], $P, 1);
15382 if($Num ne "0") {
15383 last;
15384 }
15385 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015386 }
15387 if($Num eq "0") {
15388 $Num = $_[0];
15389 }
15390 return $Num;
15391 }
15392 return $_[0];
15393}
15394
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015395sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015396{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015397 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015398 if($num!~/\./)
15399 {
15400 $num .= ".";
15401 foreach (1 .. $digs_to_cut-1) {
15402 $num .= "0";
15403 }
15404 }
15405 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
15406 {
15407 foreach (1 .. $digs_to_cut - 1 - length($1)) {
15408 $num .= "0";
15409 }
15410 }
15411 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
15412 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
15413 }
15414 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015415 if($z) {
15416 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
15417 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015418 return $num;
15419}
15420
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015421sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015422{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015423 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015424 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015425
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015426 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015427 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
15428 {
15429 my $Header = $Constants{1}{$Constant}{"Header"};
15430 if(not $Header)
15431 { # added
15432 $Header = $Constants{2}{$Constant}{"Header"}
15433 }
15434
15435 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15436 {
15437 if(not defined $CompatRules{$Level}{$Kind}) {
15438 next;
15439 }
15440 if($TargetSeverity ne getProblemSeverity($Level, $Kind)) {
15441 next;
15442 }
15443 $ReportMap{$Header}{$Constant}{$Kind} = 1;
15444 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015445 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015446
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015447 if($ReportFormat eq "xml")
15448 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015449 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015450 {
15451 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015452 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015453 {
15454 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015455 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
15456 {
15457 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
15458 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
15459 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015460
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015461 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
15462 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
15463 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
15464 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
15465 $CHANGED_CONSTANTS .= " </problem>\n";
15466 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015467 $CHANGED_CONSTANTS .= " </constant>\n";
15468 }
15469 $CHANGED_CONSTANTS .= " </header>\n";
15470 }
15471 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
15472 }
15473 else
15474 { # HTML
15475 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015476 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015477 {
15478 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015479 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015480 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015481 my $Report = "";
15482
15483 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
15484 {
15485 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
15486 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
15487 $Report .= "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
15488 $Number += 1;
15489 }
15490 if($Report)
15491 {
15492 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n";
15493 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
15494 $Report = insertIDs($Report);
15495 }
15496 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015497 }
15498 $CHANGED_CONSTANTS .= "<br/>\n";
15499 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015500 if($CHANGED_CONSTANTS)
15501 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015502 my $Title = "Problems with Constants, $TargetSeverity Severity";
15503 if($TargetSeverity eq "Safe")
15504 { # Safe Changes
15505 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015506 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015507 $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 +040015508 }
15509 }
15510 return $CHANGED_CONSTANTS;
15511}
15512
15513sub get_Report_Impl()
15514{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015515 my $CHANGED_IMPLEMENTATION = "";
15516 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015517 foreach my $Interface (sort keys(%CompatProblems_Impl))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015518 {
15519 my $HeaderName = $CompleteSignature{1}{$Interface}{"Header"};
15520 my $DyLib = $Symbol_Library{1}{$Interface};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015521 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015522 }
15523 my $Changed_Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015524 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015525 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015526 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015527 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015528 my %NameSpaceSymbols = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015529 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015530 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015531 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015532 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015533 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015534 $CHANGED_IMPLEMENTATION .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015535 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015536 foreach my $Interface (@SortedInterfaces)
15537 {
15538 $Changed_Number += 1;
15539 my $Signature = get_Signature($Interface, 1);
15540 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015541 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015542 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015543 $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 +040015544 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015545 $CHANGED_IMPLEMENTATION .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015546 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015547 }
15548 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015549 if($CHANGED_IMPLEMENTATION)
15550 {
15551 $CHANGED_IMPLEMENTATION = insertIDs($CHANGED_IMPLEMENTATION);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015552 $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 +040015553 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015554
15555 # clean memory
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015556 %CompatProblems_Impl = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015557
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015558 return $CHANGED_IMPLEMENTATION;
15559}
15560
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015561sub getTitle($$$)
15562{
15563 my ($Header, $Library, $NameSpace) = @_;
15564 my $Title = "";
15565 if($Library and $Library!~/\.\w+\Z/) {
15566 $Library .= " (.$LIB_EXT)";
15567 }
15568 if($Header and $Library)
15569 {
15570 $Title .= "<span class='h_name'>$Header</span>";
15571 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
15572 }
15573 elsif($Library) {
15574 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
15575 }
15576 elsif($Header) {
15577 $Title .= "<span class='h_name'>$Header</span><br/>\n";
15578 }
15579 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015580 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015581 }
15582 return $Title;
15583}
15584
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015585sub get_Report_Added($)
15586{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015587 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015588 my $ADDED_INTERFACES = "";
15589 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015590 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015591 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015592 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015593 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015594 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015595 {
15596 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
15597 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015598 if($Level eq "Source" and $ReportFormat eq "html")
15599 { # do not show library name in HTML report
15600 $DyLib = "";
15601 }
15602 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015603 }
15604 }
15605 }
15606 if($ReportFormat eq "xml")
15607 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015608 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015609 {
15610 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015611 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015612 {
15613 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015614 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015615 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
15616 }
15617 $ADDED_INTERFACES .= " </library>\n";
15618 }
15619 $ADDED_INTERFACES .= " </header>\n";
15620 }
15621 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
15622 }
15623 else
15624 { # HTML
15625 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015626 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015627 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015628 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015629 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015630 my %NameSpaceSymbols = ();
15631 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015632 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015633 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015634 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015635 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015636 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
15637 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015638 foreach my $Interface (@SortedInterfaces)
15639 {
15640 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015641 my $Signature = get_Signature($Interface, 2);
15642 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015643 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015644 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040015645 if($Interface=~/\A(_Z|\?)/)
15646 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015647 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015648 $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 +040015649 }
15650 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015651 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015652 }
15653 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040015654 else
15655 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015656 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015657 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015658 }
15659 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015660 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015661 }
15662 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015663 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015664 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015665 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015666 }
15667 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015668 if($ADDED_INTERFACES)
15669 {
15670 my $Anchor = "<a name='Added'></a>";
15671 if($JoinReport) {
15672 $Anchor = "<a name='".$Level."_Added'></a>";
15673 }
15674 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015675 }
15676 }
15677 return $ADDED_INTERFACES;
15678}
15679
15680sub get_Report_Removed($)
15681{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015682 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015683 my $REMOVED_INTERFACES = "";
15684 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015685 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015686 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015687 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015688 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015689 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015690 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015691 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
15692 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015693 if($Level eq "Source" and $ReportFormat eq "html")
15694 { # do not show library name in HTML report
15695 $DyLib = "";
15696 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015697 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015698 }
15699 }
15700 }
15701 if($ReportFormat eq "xml")
15702 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015703 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015704 {
15705 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015706 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015707 {
15708 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015709 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
15710 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015711 }
15712 $REMOVED_INTERFACES .= " </library>\n";
15713 }
15714 $REMOVED_INTERFACES .= " </header>\n";
15715 }
15716 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
15717 }
15718 else
15719 { # HTML
15720 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015721 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015722 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015723 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015724 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015725 my %NameSpaceSymbols = ();
15726 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015727 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015728 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015729 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015730 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015731 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
15732 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015733 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015734 {
15735 $Removed_Number += 1;
15736 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015737 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015738 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015739 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015740 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015741 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015742 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015743 if($Signature) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015744 $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 +040015745 }
15746 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015747 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015748 }
15749 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015750 else
15751 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015752 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015753 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015754 }
15755 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015756 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015757 }
15758 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015759 }
15760 }
15761 $REMOVED_INTERFACES .= "<br/>\n";
15762 }
15763 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015764 if($REMOVED_INTERFACES)
15765 {
15766 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
15767 if($JoinReport) {
15768 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
15769 }
15770 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015771 }
15772 }
15773 return $REMOVED_INTERFACES;
15774}
15775
15776sub getXmlParams($$)
15777{
15778 my ($Content, $Problem) = @_;
15779 return "" if(not $Content or not $Problem);
15780 my %XMLparams = ();
15781 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
15782 {
15783 my $Macro = "\@".lc($Attr);
15784 if($Content=~/\Q$Macro\E/) {
15785 $XMLparams{lc($Attr)} = $Problem->{$Attr};
15786 }
15787 }
15788 my @PString = ();
15789 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015790 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015791 }
15792 if(@PString) {
15793 return " ".join(" ", @PString);
15794 }
15795 else {
15796 return "";
15797 }
15798}
15799
15800sub addMarkup($)
15801{
15802 my $Content = $_[0];
15803 # auto-markup
15804 $Content=~s/\n[ ]*//; # spaces
15805 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
15806 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015807 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015808 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
15809 if($Content=~/\ANOTE:/)
15810 { # notes
15811 $Content=~s!(NOTE):!<b>$1</b>:!g;
15812 }
15813 else {
15814 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
15815 }
15816 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
15817 my @Keywords = (
15818 "void",
15819 "const",
15820 "static",
15821 "restrict",
15822 "volatile",
15823 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015824 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015825 );
15826 my $MKeys = join("|", @Keywords);
15827 foreach (@Keywords) {
15828 $MKeys .= "|non-".$_;
15829 }
15830 $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 +040015831
15832 # Markdown
15833 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
15834 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015835 return $Content;
15836}
15837
15838sub applyMacroses($$$$)
15839{
15840 my ($Level, $Kind, $Content, $Problem) = @_;
15841 return "" if(not $Content or not $Problem);
15842 $Problem->{"Word_Size"} = $WORD_SIZE{2};
15843 $Content = addMarkup($Content);
15844 # macros
15845 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
15846 {
15847 my $Macro = "\@".lc($Attr);
15848 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015849 if(not defined $Value
15850 or $Value eq "") {
15851 next;
15852 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015853 if($Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015854 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015855 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
15856 $Value=~s/\s\w+(\)|,)/$1/g; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015857 $Value = black_name($Value);
15858 }
15859 elsif($Value=~/\s/) {
15860 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
15861 }
15862 elsif($Value=~/\A\d+\Z/
15863 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
15864 { # bits to bytes
15865 if($Value % $BYTE_SIZE)
15866 { # bits
15867 if($Value==1) {
15868 $Value = "<b>".$Value."</b> bit";
15869 }
15870 else {
15871 $Value = "<b>".$Value."</b> bits";
15872 }
15873 }
15874 else
15875 { # bytes
15876 $Value /= $BYTE_SIZE;
15877 if($Value==1) {
15878 $Value = "<b>".$Value."</b> byte";
15879 }
15880 else {
15881 $Value = "<b>".$Value."</b> bytes";
15882 }
15883 }
15884 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015885 else
15886 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015887 $Value = "<b>".htmlSpecChars($Value)."</b>";
15888 }
15889 $Content=~s/\Q$Macro\E/$Value/g;
15890 }
15891
15892 if($Content=~/(\A|[^\@\w])\@\w/)
15893 {
15894 if(not $IncompleteRules{$Level}{$Kind})
15895 { # only one warning
15896 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
15897 $IncompleteRules{$Level}{$Kind} = 1;
15898 }
15899 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015900 return $Content;
15901}
15902
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015903sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015904{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015905 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015906 my $INTERFACE_PROBLEMS = "";
15907 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015908 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015909 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015910 my ($SN, $SS, $SV) = separate_symbol($Symbol);
15911 if($SV and defined $CompatProblems{$Level}{$SN}) {
15912 next;
15913 }
15914 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015915 {
15916 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015917 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015918 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015919 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
15920 my $DyLib = $Symbol_Library{1}{$Symbol};
15921 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015922 { # Symbol with Version
15923 $DyLib = $Symbol_Library{1}{$VSym};
15924 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015925 if(not $DyLib)
15926 { # const global data
15927 $DyLib = "";
15928 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015929 if($Level eq "Source" and $ReportFormat eq "html")
15930 { # do not show library name in HTML report
15931 $DyLib = "";
15932 }
15933 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
15934 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015935 {
15936 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015937 if($Priority ne $TargetSeverity) {
15938 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015939 }
15940 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015941 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
15942 {
15943 delete($SymbolChanges{$Symbol}{$Kind});
15944 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015945 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015946 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015947 }
15948 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015949 if(not keys(%{$SymbolChanges{$Symbol}})) {
15950 delete($SymbolChanges{$Symbol});
15951 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015952 }
15953 if($ReportFormat eq "xml")
15954 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015955 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015956 {
15957 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015958 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015959 {
15960 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015961 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 +040015962 {
15963 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
15964 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
15965 {
15966 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
15967 {
15968 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015969 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015970 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
15971 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
15972 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
15973 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
15974 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
15975 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
15976 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
15977 $INTERFACE_PROBLEMS .= " </problem>\n";
15978 }
15979 }
15980 $INTERFACE_PROBLEMS .= " </symbol>\n";
15981 }
15982 $INTERFACE_PROBLEMS .= " </library>\n";
15983 }
15984 $INTERFACE_PROBLEMS .= " </header>\n";
15985 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015986 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015987 }
15988 else
15989 { # HTML
15990 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015991 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015992 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015993 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015994 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015995 my (%NameSpaceSymbols, %NewSignature) = ();
15996 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015997 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015998 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015999 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016000 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016001 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016002 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 +040016003 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016004 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016005 my $Signature = get_Signature($Symbol, 1);
16006 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016007 my $ProblemNum = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016008 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016009 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016010 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016011 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016012 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016013 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016014 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016015 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016016 }
16017 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16018 {
16019 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016020 $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 +040016021 $ProblemNum += 1;
16022 $ProblemsNum += 1;
16023 }
16024 }
16025 }
16026 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016027 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016028 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016029 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016030 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016031 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016032 }
16033 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016034 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016035 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016036 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16037 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16038 if($NewSignature{$Symbol})
16039 { # argument list changed to
16040 $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 +040016041 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016042 if($Symbol=~/\A(_Z|\?)/) {
16043 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16044 }
16045 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n";
16046 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016047 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016048 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016049 }
16050 }
16051 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016052 $INTERFACE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016053 }
16054 }
16055 }
16056 if($INTERFACE_PROBLEMS)
16057 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016058 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16059 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16060 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016061 { # Safe Changes
16062 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016063 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016064 $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 +040016065 }
16066 }
16067 return $INTERFACE_PROBLEMS;
16068}
16069
16070sub get_Report_TypeProblems($$)
16071{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016072 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016073 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016074 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016075 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016076 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016077 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016078 {
16079 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16080 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016081 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016082 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016083 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016084 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016085 my $Severity = getProblemSeverity($Level, $Kind);
16086 if($Severity eq "Safe"
16087 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016088 next;
16089 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016090
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016091 if(cmpSeverities($Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target}, $Severity))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016092 { # select a problem with the highest priority
16093 next;
16094 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016095 %{$TypeChanges{$TypeName}{$Kind}{$Location}} = %{$CompatProblems{$Level}{$Interface}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016096 }
16097 }
16098 }
16099 }
16100 my %Kinds_Locations = ();
16101 foreach my $TypeName (keys(%TypeChanges))
16102 {
16103 my %Kinds_Target = ();
16104 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16105 {
16106 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
16107 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016108 my $Severity = getProblemSeverity($Level, $Kind);
16109 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016110 { # other priority
16111 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16112 next;
16113 }
16114 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16115 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
16116 if($Kinds_Target{$Kind}{$Target})
16117 { # duplicate target
16118 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16119 next;
16120 }
16121 $Kinds_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016122 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016123 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016124 }
16125 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16126 delete($TypeChanges{$TypeName}{$Kind});
16127 }
16128 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016129 if(not keys(%{$TypeChanges{$TypeName}})) {
16130 delete($TypeChanges{$TypeName});
16131 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016132 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016133 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 +040016134 if($ReportFormat eq "xml")
16135 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016136 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016137 {
16138 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016139 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016140 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016141 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016142 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16143 {
16144 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
16145 {
16146 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16147 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16148 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16149 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16150 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16151 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
16152 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
16153 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16154 $TYPE_PROBLEMS .= " </problem>\n";
16155 }
16156 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016157 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016158 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016159 $TYPE_PROBLEMS .= showVTables($TypeName);
16160 }
16161 $TYPE_PROBLEMS .= " </type>\n";
16162 }
16163 $TYPE_PROBLEMS .= " </header>\n";
16164 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016165 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016166 }
16167 else
16168 { # HTML
16169 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016170 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016171 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016172 my (%NameSpace_Type) = ();
16173 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016174 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016175 }
16176 foreach my $NameSpace (sort keys(%NameSpace_Type))
16177 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016178 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016179 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 +040016180 foreach my $TypeName (@SortedTypes)
16181 {
16182 my $ProblemNum = 1;
16183 my $TYPE_REPORT = "";
16184 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16185 {
16186 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
16187 {
16188 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16189 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16190 {
16191 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
16192 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16193 $ProblemNum += 1;
16194 $ProblemsNum += 1;
16195 }
16196 }
16197 }
16198 $ProblemNum -= 1;
16199 if($TYPE_REPORT)
16200 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016201 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016202 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016203 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016204 $ShowVTables = showVTables($TypeName);
16205 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016206
16207 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016208 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
16209 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
16210 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
16211 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016212 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016213 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016214 }
16215 }
16216 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016217 $TYPE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016218 }
16219 }
16220 if($TYPE_PROBLEMS)
16221 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016222 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
16223 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016224 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016225 { # Safe Changes
16226 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016227 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016228 $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 +040016229 }
16230 }
16231 return $TYPE_PROBLEMS;
16232}
16233
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016234sub show_Type($$$)
16235{
16236 my ($Name, $Html, $LibVersion) = @_;
16237 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
16238 $TType = lc($TType);
16239 if($TType=~/struct|union|enum/) {
16240 $Name=~s/\A\Q$TType\E //g;
16241 }
16242 if($Html) {
16243 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
16244 }
16245 else {
16246 $Name = $TType." ".$Name;
16247 }
16248 return $Name;
16249}
16250
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016251sub get_Anchor($$$)
16252{
16253 my ($Kind, $Level, $Severity) = @_;
16254 if($JoinReport)
16255 {
16256 if($Severity eq "Safe") {
16257 return "Other_".$Level."_Changes_In_".$Kind."s";
16258 }
16259 else {
16260 return $Kind."_".$Level."_Problems_".$Severity;
16261 }
16262 }
16263 else
16264 {
16265 if($Severity eq "Safe") {
16266 return "Other_Changes_In_".$Kind."s";
16267 }
16268 else {
16269 return $Kind."_Problems_".$Severity;
16270 }
16271 }
16272}
16273
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016274sub showVTables($)
16275{
16276 my $TypeName = $_[0];
16277 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016278 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016279 if(defined $Type1{"VTable"}
16280 and keys(%{$Type1{"VTable"}}))
16281 {
16282 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016283 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016284 if(defined $Type2{"VTable"}
16285 and keys(%{$Type2{"VTable"}}))
16286 {
16287 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
16288 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016289 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016290 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016291 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
16292 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016293 }
16294 my $VTABLES = "";
16295 if($ReportFormat eq "xml")
16296 { # XML
16297 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016298 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016299 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016300 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016301 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
16302 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016303 $VTABLES .= " </entry>\n";
16304 }
16305 $VTABLES .= " </vtable>\n\n";
16306 }
16307 else
16308 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016309 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016310 $VTABLES .= "<tr><th width='2%'>Offset</th>";
16311 $VTABLES .= "<th width='45%'>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
16312 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016313 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016314 {
16315 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016316 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016317 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016318 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016319 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016320 $Color1 = " class='failed'";
16321 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016322 }
16323 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016324 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016325 }
16326 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016327 $VTABLES .= "<tr><th>".$Index."</th>\n";
16328 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
16329 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016330 }
16331 $VTABLES .= "</table><br/>\n";
16332 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016333 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016334 }
16335 return $VTABLES;
16336 }
16337 }
16338 return "";
16339}
16340
16341sub simpleVEntry($)
16342{
16343 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016344 if(not defined $VEntry
16345 or $VEntry eq "") {
16346 return "";
16347 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016348 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
16349 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
16350 if($VEntry=~/\A_ZThn.+\Z/) {
16351 $VEntry = "non-virtual thunk";
16352 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016353 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016354 # support for old GCC versions
16355 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
16356 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
16357 $VEntry=~s/\A&_Z\Z/& _Z/;
16358 # templates
16359 if($VEntry=~s/ \[with (\w+) = (.+?)(, [^=]+ = .+|])\Z//g)
16360 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
16361 # become std::basic_streambuf<char, ...>::imbue
16362 my ($Pname, $Pval) = ($1, $2);
16363 if($Pname eq "_CharT" and $VEntry=~/\Astd::/)
16364 { # stdc++ typedefs
16365 $VEntry=~s/<$Pname(, [^<>]+|)>/<$Pval>/g;
16366 # FIXME: simplify names using stdcxx typedefs (StdCxxTypedef)
16367 # The typedef info should be added to ABI dumps
16368 }
16369 else
16370 {
16371 $VEntry=~s/<$Pname>/<$Pval>/g;
16372 $VEntry=~s/<$Pname, [^<>]+>/<$Pval, ...>/g;
16373 }
16374 }
16375 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
16376 return $VEntry;
16377}
16378
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016379sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016380{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016381 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016382 my $LIMIT = 1000;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016383 if($#{$Syms}>=10000)
16384 { # reduce size of the report
16385 $LIMIT = 10;
16386 }
16387 my %SProblems = ();
16388 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016389 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016390 if(keys(%SProblems)>$LIMIT) {
16391 last;
16392 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016393 if(($Symbol=~/C2E|D2E|D0E/))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016394 { # duplicated problems for C2 constructors, D2 and D0 destructors
16395 next;
16396 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016397 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16398 if($Level eq "Source")
16399 { # remove symbol version
16400 $Symbol=$SN;
16401 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016402 my ($MinPath_Length, $ProblemLocation_Last) = (-1, "");
16403 my $Severity_Max = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016404 my $Signature = get_Signature($Symbol, 1);
16405 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016406 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016407 foreach my $Location (keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016408 {
16409 if(not defined $Kinds_Locations->{$Kind}
16410 or not $Kinds_Locations->{$Kind}{$Location}) {
16411 next;
16412 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016413 if($SV and defined $CompatProblems{$Level}{$SN}
16414 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Location})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016415 { # duplicated problems for versioned symbols
16416 next;
16417 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016418 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016419 next if($Type_Name ne $Target_TypeName);
16420
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016421 my $Position = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Param_Pos"};
16422 my $Param_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Param_Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016423 my $Severity = getProblemSeverity($Level, $Kind);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016424 my $Path_Length = 0;
16425 my $ProblemLocation = $Location;
16426 if($Type_Name) {
16427 $ProblemLocation=~s/->\Q$Type_Name\E\Z//g;
16428 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016429 while($ProblemLocation=~/\-\>/g) {
16430 $Path_Length += 1;
16431 }
16432 if($MinPath_Length==-1 or ($Path_Length<=$MinPath_Length and $Severity_Val{$Severity}>$Severity_Max)
16433 or (cmp_locations($ProblemLocation, $ProblemLocation_Last) and $Severity_Val{$Severity}==$Severity_Max))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016434 {
16435 $MinPath_Length = $Path_Length;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016436 $Severity_Max = $Severity_Val{$Severity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016437 $ProblemLocation_Last = $ProblemLocation;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016438 %{$SProblems{$Symbol}} = (
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016439 "Descr"=>getAffectDescription($Level, $Symbol, $Kind, $Location),
16440 "Severity_Max"=>$Severity_Max,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016441 "Signature"=>$Signature,
16442 "Position"=>$Position,
16443 "Param_Name"=>$Param_Name,
16444 "Location"=>$Location
16445 );
16446 }
16447 }
16448 }
16449 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016450 my @Symbols = keys(%SProblems);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016451 @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 +040016452 @Symbols = sort {$SProblems{$b}{"Severity_Max"}<=>$SProblems{$a}{"Severity_Max"}} @Symbols;
16453 if($#Symbols+1>$LIMIT)
16454 { # remove last element
16455 pop(@Symbols);
16456 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016457 my $Affected = "";
16458 if($ReportFormat eq "xml")
16459 { # XML
16460 $Affected .= " <affected>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016461 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016462 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016463 my $Param_Name = $SProblems{$Symbol}{"Param_Name"};
16464 my $Description = $SProblems{$Symbol}{"Descr"};
16465 my $Location = $SProblems{$Symbol}{"Location"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016466 my $Target = "";
16467 if($Param_Name) {
16468 $Target = " affected=\"param\" param_name=\"$Param_Name\"";
16469 }
16470 elsif($Location=~/\Aretval(\-|\Z)/i) {
16471 $Target = " affected=\"retval\"";
16472 }
16473 elsif($Location=~/\Athis(\-|\Z)/i) {
16474 $Target = " affected=\"this\"";
16475 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016476 $Affected .= " <symbol$Target name=\"$Symbol\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016477 $Affected .= " <comment>".xmlSpecChars($Description)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016478 $Affected .= " </symbol>\n";
16479 }
16480 $Affected .= " </affected>\n";
16481 }
16482 else
16483 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016484 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016485 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016486 my $Description = $SProblems{$Symbol}{"Descr"};
16487 my $Signature = $SProblems{$Symbol}{"Signature"};
16488 my $Pos = $SProblems{$Symbol}{"Position"};
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016489 $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 +040016490 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016491 if(keys(%SProblems)>$LIMIT) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016492 $Affected .= "and others ...<br/>";
16493 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016494 $Affected = "<div class='affected'>".$Affected."</div>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016495 if($Affected)
16496 {
16497 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016498 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".(keys(%SProblems)>$LIMIT?">".$LIMIT:keys(%SProblems)).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016499 }
16500 }
16501 return $Affected;
16502}
16503
16504sub cmp_locations($$)
16505{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016506 my ($L1, $L2) = @_;
16507 if($L2=~/\b(retval|this)\b/
16508 and $L1!~/\b(retval|this)\b/ and $L1!~/\-\>/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016509 return 1;
16510 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016511 if($L2=~/\b(retval|this)\b/ and $L2=~/\-\>/
16512 and $L1!~/\b(retval|this)\b/ and $L1=~/\-\>/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016513 return 1;
16514 }
16515 return 0;
16516}
16517
16518sub getAffectDescription($$$$)
16519{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016520 my ($Level, $Symbol, $Kind, $Location) = @_;
16521 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016522 my $PPos = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016523 my @Sentence = ();
16524 $Location=~s/\A(.*)\-\>.+?\Z/$1/;
16525 if($Kind eq "Overridden_Virtual_Method"
16526 or $Kind eq "Overridden_Virtual_Method_B") {
16527 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
16528 }
16529 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16530 {
16531 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
16532 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016533 my $METHOD_TYPE = $CompleteSignature{1}{$Symbol}{"Constructor"}?"constructor":"method";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016534 my $ClassName = $TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016535 if($ClassName eq $Problem{"Type_Name"}) {
16536 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
16537 }
16538 else {
16539 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
16540 }
16541 }
16542 else
16543 {
16544 if($Location=~/retval/)
16545 { # return value
16546 if($Location=~/\-\>/) {
16547 push(@Sentence, "Field \'".$Location."\' in return value");
16548 }
16549 else {
16550 push(@Sentence, "Return value");
16551 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016552 if(my $Init = $Problem{"InitialType_Type"})
16553 {
16554 if($Init eq "Pointer") {
16555 push(@Sentence, "(pointer)");
16556 }
16557 elsif($Init eq "Ref") {
16558 push(@Sentence, "(reference)");
16559 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016560 }
16561 }
16562 elsif($Location=~/this/)
16563 { # "this" pointer
16564 if($Location=~/\-\>/) {
16565 push(@Sentence, "Field \'".$Location."\' in the object of this method");
16566 }
16567 else {
16568 push(@Sentence, "\'this\' pointer");
16569 }
16570 }
16571 else
16572 { # parameters
16573 if($Location=~/\-\>/) {
16574 push(@Sentence, "Field \'".$Location."\' in $PPos parameter");
16575 }
16576 else {
16577 push(@Sentence, "$PPos parameter");
16578 }
16579 if($Problem{"Param_Name"}) {
16580 push(@Sentence, "\'".$Problem{"Param_Name"}."\'");
16581 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016582 if(my $Init = $Problem{"InitialType_Type"})
16583 {
16584 if($Init eq "Pointer") {
16585 push(@Sentence, "(pointer)");
16586 }
16587 elsif($Init eq "Ref") {
16588 push(@Sentence, "(reference)");
16589 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016590 }
16591 }
16592 if($Location eq "this") {
16593 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
16594 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016595 elsif(defined $Problem{"Start_Type_Name"}
16596 and $Problem{"Start_Type_Name"} eq $Problem{"Type_Name"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016597 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
16598 }
16599 else {
16600 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
16601 }
16602 }
16603 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016604 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016605 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 +040016606 }
16607 return join(" ", @Sentence);
16608}
16609
16610sub get_XmlSign($$)
16611{
16612 my ($Symbol, $LibVersion) = @_;
16613 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
16614 my $Report = "";
16615 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
16616 {
16617 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016618 my $Type = $Info->{"Param"}{$Pos}{"type"};
16619 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016620 foreach my $Typedef (keys(%ChangedTypedef))
16621 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016622 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
16623 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
16624 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016625 }
16626 $Report .= " <param pos=\"$Pos\">\n";
16627 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016628 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016629 $Report .= " </param>\n";
16630 }
16631 if(my $Return = $Info->{"Return"})
16632 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016633 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016634 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016635 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016636 $Report .= " </retval>\n";
16637 }
16638 return $Report;
16639}
16640
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016641sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016642{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016643 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016644 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016645 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016646 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016647 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16648 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016649 next;
16650 }
16651 $Report .= " <symbol name=\"$Symbol\">\n";
16652 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016653 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016654 {
16655 if(defined $CompleteSignature{1}{$Symbol}
16656 and defined $CompleteSignature{1}{$Symbol}{"Header"})
16657 {
16658 $P1 = get_XmlSign($Symbol, 1);
16659 $S1 = get_Signature($Symbol, 1);
16660 }
16661 elsif($Symbol=~/\A(_Z|\?)/) {
16662 $S1 = $tr_name{$Symbol};
16663 }
16664 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016665 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016666 {
16667 if(defined $CompleteSignature{2}{$Symbol}
16668 and defined $CompleteSignature{2}{$Symbol}{"Header"})
16669 {
16670 $P2 = get_XmlSign($Symbol, 2);
16671 $S2 = get_Signature($Symbol, 2);
16672 }
16673 elsif($Symbol=~/\A(_Z|\?)/) {
16674 $S2 = $tr_name{$Symbol};
16675 }
16676 }
16677 if($S1)
16678 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016679 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016680 $Report .= $P1;
16681 $Report .= " </old>\n";
16682 }
16683 if($S2 and $S2 ne $S1)
16684 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016685 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016686 $Report .= $P2;
16687 $Report .= " </new>\n";
16688 }
16689 $Report .= " </symbol>\n";
16690 }
16691 $Report .= "</symbols_info>\n";
16692 return $Report;
16693}
16694
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016695sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016696{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016697 my ($Level, $Report) = @_;
16698 if($ReportFormat eq "xml") {
16699 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016700 }
16701 if($StdOut)
16702 { # --stdout option
16703 print STDOUT $Report;
16704 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016705 else
16706 {
16707 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016708 mkpath(get_dirname($RPath));
16709
16710 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
16711 print REPORT $Report;
16712 close(REPORT);
16713
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016714 if($Browse or $OpenReport)
16715 { # open in browser
16716 openReport($RPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016717 if($JoinReport or $DoubleReport)
16718 {
16719 if($Level eq "Binary")
16720 { # wait to open a browser
16721 sleep(1);
16722 }
16723 }
16724 }
16725 }
16726}
16727
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016728sub openReport($)
16729{
16730 my $Path = $_[0];
16731 my $Cmd = "";
16732 if($Browse)
16733 { # user-defined browser
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016734 $Cmd = $Browse." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016735 }
16736 if(not $Cmd)
16737 { # default browser
16738 if($OSgroup eq "macos") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040016739 $Cmd = "open \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016740 }
16741 elsif($OSgroup eq "windows") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040016742 $Cmd = "start ".path_format($Path, $OSgroup);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016743 }
16744 else
16745 { # linux, freebsd, solaris
16746 my @Browsers = (
16747 "x-www-browser",
16748 "sensible-browser",
16749 "firefox",
16750 "opera",
16751 "xdg-open",
16752 "lynx",
16753 "links"
16754 );
16755 foreach my $Br (@Browsers)
16756 {
16757 if($Br = get_CmdPath($Br))
16758 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016759 $Cmd = $Br." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016760 last;
16761 }
16762 }
16763 }
16764 }
16765 if($Cmd)
16766 {
16767 if($Debug) {
16768 printMsg("INFO", "running $Cmd");
16769 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040016770 if($OSgroup ne "windows"
16771 and $OSgroup ne "macos")
16772 {
16773 if($Cmd!~/lynx|links/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016774 $Cmd .= " >\"/dev/null\" 2>&1 &";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040016775 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016776 }
16777 system($Cmd);
16778 }
16779 else {
16780 printMsg("ERROR", "cannot open report in browser");
16781 }
16782}
16783
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016784sub getReport($)
16785{
16786 my $Level = $_[0];
16787 if($ReportFormat eq "xml")
16788 { # XML
16789
16790 if($Level eq "Join")
16791 {
16792 my $Report = "<reports>\n";
16793 $Report .= getReport("Binary");
16794 $Report .= getReport("Source");
16795 $Report .= "</reports>\n";
16796 return $Report;
16797 }
16798 else
16799 {
16800 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
16801 my ($Summary, $MetaData) = get_Summary($Level);
16802 $Report .= $Summary."\n";
16803 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
16804 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
16805 $Report .= get_Report_SymbolsInfo($Level);
16806 $Report .= "</report>\n";
16807 return $Report;
16808 }
16809 }
16810 else
16811 { # HTML
16812 my $CssStyles = readModule("Styles", "Report.css");
16813 my $JScripts = readModule("Scripts", "Sections.js");
16814 if($Level eq "Join")
16815 {
16816 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
16817 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040016818 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
16819 my $Keywords = $TargetLibraryFName.", compatibility, API, report";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016820 my $Description = "Compatibility report for the $TargetLibraryFName $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
16821 my ($BSummary, $BMetaData) = get_Summary("Binary");
16822 my ($SSummary, $SMetaData) = get_Summary("Source");
16823 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>";
16824 $Report .= get_Report_Header("Join")."
16825 <br/><div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016826 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
16827 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016828 </div>";
16829 $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>";
16830 $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 +040016831 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016832 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
16833 return $Report;
16834 }
16835 else
16836 {
16837 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040016838 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
16839 my $Keywords = $TargetLibraryFName.", ".lc($Level)." compatibility, API, report";
16840 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 +040016841 if($Level eq "Binary")
16842 {
16843 if(getArch(1) eq getArch(2)
16844 and getArch(1) ne "unknown") {
16845 $Description .= " on ".showArch(getArch(1));
16846 }
16847 }
16848 my $Report = "<!-\- $MetaData -\->\n".composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."\n<body>\n<div><a name='Top'></a>\n";
16849 $Report .= get_Report_Header($Level)."\n".$Summary."\n";
16850 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
16851 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
16852 $Report .= get_SourceInfo();
16853 $Report .= "</div>\n<br/><br/><br/><hr/>\n";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016854 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016855 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
16856 return $Report;
16857 }
16858 }
16859}
16860
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016861sub getLegend()
16862{
16863 return "<br/>
16864<table class='summary'>
16865<tr>
16866 <td class='new'>added</td>
16867 <td class='passed'>compatible</td>
16868</tr>
16869<tr>
16870 <td class='warning'>warning</td>
16871 <td class='failed'>incompatible</td>
16872</tr></table>\n";
16873}
16874
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016875sub createReport()
16876{
16877 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016878 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016879 writeReport("Join", getReport("Join"));
16880 }
16881 elsif($DoubleReport)
16882 { # default
16883 writeReport("Binary", getReport("Binary"));
16884 writeReport("Source", getReport("Source"));
16885 }
16886 elsif($BinaryOnly)
16887 { # --binary
16888 writeReport("Binary", getReport("Binary"));
16889 }
16890 elsif($SourceOnly)
16891 { # --source
16892 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016893 }
16894}
16895
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016896sub getReportFooter($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016897{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016898 my ($LibName, $Wide) = @_;
16899 my $FooterStyle = $Wide?"width:99%":"width:97%;padding-top:3px";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016900 my $Footer = "<div style='$FooterStyle;font-size:11px;' align='right'><i>Generated on ".(localtime time); # report date
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016901 $Footer .= " for <span style='font-weight:bold'>$LibName</span>"; # tested library/system name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016902 $Footer .= " by <a href='".$HomePage{"Wiki"}."'>ABI Compliance Checker</a>"; # tool name
16903 my $ToolSummary = "<br/>A tool for checking backward compatibility of a C/C++ library API&#160;&#160;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016904 $Footer .= " $TOOL_VERSION &#160;$ToolSummary</i></div>"; # tool version
16905 return $Footer;
16906}
16907
16908sub get_Report_Problems($$)
16909{
16910 my ($Priority, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016911 my $Report = get_Report_TypeProblems($Priority, $Level);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016912 if(my $SProblems = get_Report_SymbolProblems($Priority, $Level)) {
16913 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016914 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016915 if($Priority eq "Low")
16916 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016917 $Report .= get_Report_ChangedConstants("Low", $Level);
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +040016918 if($ReportFormat eq "html")
16919 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016920 if($CheckImpl and $Level eq "Binary") {
16921 $Report .= get_Report_Impl();
16922 }
16923 }
16924 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016925 if($Priority eq "Safe")
16926 {
16927 $Report .= get_Report_ChangedConstants("Safe", $Level);
16928 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016929 if($ReportFormat eq "html")
16930 {
16931 if($Report)
16932 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016933 if($JoinReport)
16934 {
16935 if($Priority eq "Safe") {
16936 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
16937 }
16938 else {
16939 $Report = "<a name=\'".$Priority."_Risk_".$Level."_Problems\'></a>".$Report;
16940 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016941 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016942 else
16943 {
16944 if($Priority eq "Safe") {
16945 $Report = "<a name=\'Other_Changes\'></a>".$Report;
16946 }
16947 else {
16948 $Report = "<a name=\'".$Priority."_Risk_Problems\'></a>".$Report;
16949 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016950 }
16951 }
16952 }
16953 return $Report;
16954}
16955
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016956sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016957{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016958 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
16959 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
16960 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
16961 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016962 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
16963 <meta name=\"keywords\" content=\"$Keywords\" />
16964 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016965 <title>
16966 $Title
16967 </title>
16968 <style type=\"text/css\">
16969 $Styles
16970 </style>
16971 <script type=\"text/javascript\" language=\"JavaScript\">
16972 <!--
16973 $Scripts
16974 -->
16975 </script>
16976 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016977}
16978
16979sub insertIDs($)
16980{
16981 my $Text = $_[0];
16982 while($Text=~/CONTENT_ID/)
16983 {
16984 if(int($Content_Counter)%2) {
16985 $ContentID -= 1;
16986 }
16987 $Text=~s/CONTENT_ID/c_$ContentID/;
16988 $ContentID += 1;
16989 $Content_Counter += 1;
16990 }
16991 return $Text;
16992}
16993
16994sub checkPreprocessedUnit($)
16995{
16996 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016997 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016998 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016999 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017000
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017001 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017002 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017003 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017004 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017005 chomp($Line);
17006 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017007 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017008 $CurHeader = path_format($1, $OSgroup);
17009 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017010 $CurClass = "";
17011
17012 if(index($CurHeader, $TMP_DIR)==0) {
17013 next;
17014 }
17015
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017016 if(substr($CurHeaderName, 0, 1) eq "<")
17017 { # <built-in>, <command-line>, etc.
17018 $CurHeaderName = "";
17019 $CurHeader = "";
17020 }
17021
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017022 if($ExtraInfo)
17023 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017024 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017025 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17026 }
17027 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017028 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017029 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017030 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017031 if($CurHeaderName)
17032 {
17033 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17034 and not $Registered_Headers{$Version}{$CurHeader})
17035 { # not a target
17036 next;
17037 }
17038 if(not is_target_header($CurHeaderName, 1)
17039 and not is_target_header($CurHeaderName, 2))
17040 { # user-defined header
17041 next;
17042 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017043 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017044 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017045
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017046 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017047 {
17048 my ($Name, $Value) = ($1, $2);
17049 if(not $Constants{$Version}{$Name}{"Access"})
17050 {
17051 $Constants{$Version}{$Name}{"Access"} = "public";
17052 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017053 if($CurHeaderName) {
17054 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17055 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017056 }
17057 }
17058 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17059 $Constants{$Version}{$1}{"Access"} = "private";
17060 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017061 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017062 else
17063 {
17064 if(defined $ExtraDump)
17065 {
17066 if($Line=~/(\w+)\s*\(/)
17067 { # functions
17068 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17069 }
17070 #elsif($Line=~/(\w+)\s*;/)
17071 #{ # data
17072 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17073 #}
17074 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17075 $CurClass = $2;
17076 }
17077 }
17078 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017079 }
17080 close(PREPROC);
17081 foreach my $Constant (keys(%{$Constants{$Version}}))
17082 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017083 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17084 {
17085 delete($Constants{$Version}{$Constant});
17086 next;
17087 }
17088 if(not $ExtraDump and ($Constant=~/_h\Z/i or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
17089 { # skip
17090 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017091 }
17092 else {
17093 delete($Constants{$Version}{$Constant}{"Access"});
17094 }
17095 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017096 if($Debug)
17097 {
17098 mkpath($DEBUG_PATH{$Version});
17099 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17100 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017101}
17102
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017103sub uncoverConstant($$)
17104{
17105 my ($LibVersion, $Constant) = @_;
17106 return "" if(not $LibVersion or not $Constant);
17107 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17108 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17109 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17110 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017111
17112 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017113 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017114 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17115 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017116 {
17117 push(@RecurConstant, $Constant);
17118 my $Uncovered = uncoverConstant($LibVersion, $Value);
17119 if($Uncovered ne "") {
17120 $Value = $Uncovered;
17121 }
17122 pop(@RecurConstant);
17123 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017124
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017125 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017126 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017127 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17128 }
17129 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17130}
17131
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017132sub simpleConstant($$)
17133{
17134 my ($LibVersion, $Value) = @_;
17135 if($Value=~/\W/)
17136 {
17137 my $Value_Copy = $Value;
17138 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
17139 {
17140 my $Word = $1;
17141 if($Value!~/$Word\s*\(/)
17142 {
17143 my $Val = uncoverConstant($LibVersion, $Word);
17144 if($Val ne "")
17145 {
17146 $Value=~s/\b$Word\b/$Val/g;
17147 }
17148 }
17149 }
17150 }
17151 return $Value;
17152}
17153
17154sub computeValue($)
17155{
17156 my $Value = $_[0];
17157
17158 if($Value=~/\A\((-?[\d]+)\)\Z/) {
17159 return $1;
17160 }
17161
17162 if($Value=~/\A[\d\-\+()]+\Z/) {
17163 return eval($Value);
17164 }
17165
17166 return $Value;
17167}
17168
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017169my %IgnoreConstant = map {$_=>1} (
17170 "VERSION",
17171 "VERSIONCODE",
17172 "VERNUM",
17173 "VERS_INFO",
17174 "PATCHLEVEL",
17175 "INSTALLPREFIX",
17176 "VBUILD",
17177 "VPATCH",
17178 "VMINOR",
17179 "BUILD_STRING",
17180 "BUILD_TIME",
17181 "PACKAGE_STRING",
17182 "PRODUCTION",
17183 "CONFIGURE_COMMAND",
17184 "INSTALLDIR",
17185 "BINDIR",
17186 "CONFIG_FILE_PATH",
17187 "DATADIR",
17188 "EXTENSION_DIR",
17189 "INCLUDE_PATH",
17190 "LIBDIR",
17191 "LOCALSTATEDIR",
17192 "SBINDIR",
17193 "SYSCONFDIR",
17194 "RELEASE",
17195 "SOURCE_ID",
17196 "SUBMINOR",
17197 "MINOR",
17198 "MINNOR",
17199 "MINORVERSION",
17200 "MAJOR",
17201 "MAJORVERSION",
17202 "MICRO",
17203 "MICROVERSION",
17204 "BINARY_AGE",
17205 "INTERFACE_AGE",
17206 "CORE_ABI",
17207 "PATCH",
17208 "COPYRIGHT",
17209 "TIMESTAMP",
17210 "REVISION",
17211 "PACKAGE_TAG",
17212 "PACKAGEDATE",
17213 "NUMVERSION",
17214 "Release",
17215 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017216);
17217
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017218sub constantFilter($$$)
17219{
17220 my ($Name, $Value, $Level) = @_;
17221
17222 if($Level eq "Binary")
17223 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017224 if($Name=~/_t\Z/)
17225 { # __malloc_ptr_t
17226 return 1;
17227 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017228 foreach (keys(%IgnoreConstant))
17229 {
17230 if($Name=~/(\A|_)$_(_|\Z)/)
17231 { # version
17232 return 1;
17233 }
17234 if(/\A[A-Z].*[a-z]\Z/)
17235 {
17236 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
17237 { # version
17238 return 1;
17239 }
17240 }
17241 }
17242 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
17243 { # version
17244 return 1;
17245 }
17246 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
17247 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
17248 return 1;
17249 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017250
17251 if($Value=~/\A["'].*['"]/i)
17252 { # string
17253 return 0;
17254 }
17255
17256 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
17257 { # static int gcry_pth_init
17258 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017259 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017260 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017261 return 1;
17262 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017263 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017264 { # foo(p)
17265 return 1;
17266 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017267 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017268 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017269 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017270 return 1;
17271 }
17272 }
17273
17274 return 0;
17275}
17276
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017277sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017278{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017279 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017280 foreach my $Constant (keys(%{$Constants{1}}))
17281 {
17282 if($SkipConstants{1}{$Constant})
17283 { # skipped by the user
17284 next;
17285 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017286
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017287 if(my $Header = $Constants{1}{$Constant}{"Header"})
17288 {
17289 if(not is_target_header($Header, 1)
17290 and not is_target_header($Header, 2))
17291 { # user-defined header
17292 next;
17293 }
17294 }
17295 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017296 next;
17297 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017298
17299 my $Old_Value = uncoverConstant(1, $Constant);
17300
17301 if(constantFilter($Constant, $Old_Value, $Level))
17302 { # separate binary and source problems
17303 next;
17304 }
17305
17306 if(not defined $Constants{2}{$Constant}{"Value"})
17307 { # removed
17308 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
17309 "Target"=>$Constant,
17310 "Old_Value"=>$Old_Value );
17311 next;
17312 }
17313
17314 if($Constants{2}{$Constant}{"Value"} eq "")
17315 { # empty value
17316 # TODO: implement a rule
17317 next;
17318 }
17319
17320 my $New_Value = uncoverConstant(2, $Constant);
17321
17322 my $Old_Value_Pure = $Old_Value;
17323 my $New_Value_Pure = $New_Value;
17324
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017325 $Old_Value_Pure=~s/(\W)\s+/$1/g;
17326 $Old_Value_Pure=~s/\s+(\W)/$1/g;
17327 $New_Value_Pure=~s/(\W)\s+/$1/g;
17328 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017329
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017330 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017331
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017332 if($New_Value_Pure ne $Old_Value_Pure)
17333 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017334 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
17335 { # complex values
17336 next;
17337 }
17338 if(computeValue($Old_Value) eq computeValue($New_Value))
17339 { # expressions
17340 next;
17341 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017342 if(convert_integer($Old_Value) eq convert_integer($New_Value))
17343 { # 0x0001 and 0x1, 0x1 and 1 equal constants
17344 next;
17345 }
17346 if($Old_Value eq "0" and $New_Value eq "NULL")
17347 { # 0 => NULL
17348 next;
17349 }
17350 if($Old_Value eq "NULL" and $New_Value eq "0")
17351 { # NULL => 0
17352 next;
17353 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017354 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017355 "Target"=>$Constant,
17356 "Old_Value"=>$Old_Value,
17357 "New_Value"=>$New_Value );
17358 }
17359 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017360
17361 foreach my $Constant (keys(%{$Constants{2}}))
17362 {
17363 if(not defined $Constants{1}{$Constant}{"Value"})
17364 {
17365 if($SkipConstants{2}{$Constant})
17366 { # skipped by the user
17367 next;
17368 }
17369
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017370 if(my $Header = $Constants{2}{$Constant}{"Header"})
17371 {
17372 if(not is_target_header($Header, 1)
17373 and not is_target_header($Header, 2))
17374 { # user-defined header
17375 next;
17376 }
17377 }
17378 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017379 next;
17380 }
17381
17382 my $New_Value = uncoverConstant(2, $Constant);
17383 if(not defined $New_Value or $New_Value eq "") {
17384 next;
17385 }
17386
17387 if(constantFilter($Constant, $New_Value, $Level))
17388 { # separate binary and source problems
17389 next;
17390 }
17391
17392 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
17393 "Target"=>$Constant,
17394 "New_Value"=>$New_Value );
17395 }
17396 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017397}
17398
17399sub convert_integer($)
17400{
17401 my $Value = $_[0];
17402 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017403 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017404 return hex($Value);
17405 }
17406 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017407 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017408 return oct($Value);
17409 }
17410 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017411 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017412 return oct($Value);
17413 }
17414 else {
17415 return $Value;
17416 }
17417}
17418
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017419sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017420{
17421 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017422 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017423 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017424 {
17425 if($LibVersion==1)
17426 {
17427 printMsg("WARNING", "checking headers only");
17428 $CheckHeadersOnly = 1;
17429 }
17430 else {
17431 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
17432 }
17433 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017434
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017435 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017436 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017437 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017438
17439 if($CheckUndefined)
17440 {
17441 my %UndefinedLibs = ();
17442
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017443 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
17444
17445 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017446 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017447 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017448 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017449 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017450 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017451 if($Symbol_Library{$LibVersion}{$Symbol}
17452 or $DepSymbol_Library{$LibVersion}{$Symbol})
17453 { # exported by target library
17454 next;
17455 }
17456 if(index($Symbol, '@')!=-1)
17457 { # exported default symbol version (@@)
17458 $Symbol=~s/\@/\@\@/;
17459 if($Symbol_Library{$LibVersion}{$Symbol}
17460 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
17461 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017462 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017463 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017464 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
17465 $UndefinedLibs{$Path} = 1;
17466 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017467 }
17468 }
17469 }
17470 if($ExtraInfo)
17471 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017472 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017473 {
17474 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017475 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017476 foreach (@Paths)
17477 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017478 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017479 my ($Dir, $Name) = separate_path($_);
17480
17481 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017482 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017483 }
17484
17485 $Name = parse_libname($Name, "name", $OStarget);
17486 $Name=~s/\Alib//;
17487
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017488 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017489 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017490
17491 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
17492 {
17493 $LibString = " -L".esc($Dir).$LibString;
17494 }
17495
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017496 writeFile($ExtraInfo."/libs-string", $LibString);
17497 }
17498 }
17499 }
17500
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017501 if($ExtraInfo) {
17502 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
17503 }
17504
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017505 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017506 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017507 if($#LibPaths!=-1)
17508 {
17509 if(not keys(%{$Symbol_Library{$LibVersion}}))
17510 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017511 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017512 printMsg("WARNING", "checking headers only");
17513 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017514 }
17515 }
17516 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017517
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017518 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017519 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017520}
17521
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017522my %Prefix_Lib_Map=(
17523 # symbols for autodetecting library dependencies (by prefix)
17524 "pthread_" => ["libpthread"],
17525 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
17526 "cairo_" => ["libcairo"],
17527 "gtk_" => ["libgtk-x11-2.0"],
17528 "atk_" => ["libatk-1.0"],
17529 "gdk_" => ["libgdk-x11-2.0"],
17530 "gl" => ["libGL"],
17531 "glu" => ["libGLU"],
17532 "popt" => ["libpopt"],
17533 "Py" => ["libpython"],
17534 "jpeg_" => ["libjpeg"],
17535 "BZ2_" => ["libbz2"],
17536 "Fc" => ["libfontconfig"],
17537 "Xft" => ["libXft"],
17538 "SSL_" => ["libssl"],
17539 "sem_" => ["libpthread"],
17540 "snd_" => ["libasound"],
17541 "art_" => ["libart_lgpl_2"],
17542 "dbus_g" => ["libdbus-glib-1"],
17543 "GOMP_" => ["libgomp"],
17544 "omp_" => ["libgomp"],
17545 "cms" => ["liblcms"]
17546);
17547
17548my %Pattern_Lib_Map=(
17549 "SL[a-z]" => ["libslang"]
17550);
17551
17552my %Symbol_Lib_Map=(
17553 # symbols for autodetecting library dependencies (by name)
17554 "pow" => "libm",
17555 "fmod" => "libm",
17556 "sin" => "libm",
17557 "floor" => "libm",
17558 "cos" => "libm",
17559 "dlopen" => "libdl",
17560 "deflate" => "libz",
17561 "inflate" => "libz",
17562 "move_panel" => "libpanel",
17563 "XOpenDisplay" => "libX11",
17564 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017565 "clock_gettime" => "librt",
17566 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017567);
17568
17569sub find_SymbolLibs($$)
17570{
17571 my ($LibVersion, $Symbol) = @_;
17572
17573 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
17574 { # debug symbols
17575 return ();
17576 }
17577
17578 my %Paths = ();
17579
17580 if(my $LibName = $Symbol_Lib_Map{$Symbol})
17581 {
17582 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
17583 $Paths{$Path} = 1;
17584 }
17585 }
17586
17587 if(my $SymbolPrefix = getPrefix($Symbol))
17588 {
17589 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
17590 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
17591 }
17592
17593 if(not keys(%Paths))
17594 {
17595 if(defined $Prefix_Lib_Map{$SymbolPrefix})
17596 {
17597 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
17598 {
17599 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
17600 $Paths{$Path} = 1;
17601 }
17602 }
17603 }
17604 }
17605
17606 if(not keys(%Paths))
17607 {
17608 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
17609 {
17610 if($Symbol=~/\A$Prefix/)
17611 {
17612 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
17613 {
17614 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
17615 $Paths{$Path} = 1;
17616 }
17617 }
17618 }
17619 }
17620 }
17621
17622 if(not keys(%Paths))
17623 {
17624 if($SymbolPrefix)
17625 { # try to find a library by symbol prefix
17626 if($SymbolPrefix eq "inotify" and
17627 index($Symbol, "\@GLIBC")!=-1)
17628 {
17629 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
17630 $Paths{$Path} = 1;
17631 }
17632 }
17633 else
17634 {
17635 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
17636 $Paths{$Path} = 1;
17637 }
17638 }
17639 }
17640 }
17641
17642 if(my @Paths = keys(%Paths)) {
17643 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
17644 }
17645 }
17646 return keys(%Paths);
17647}
17648
17649sub get_LibPath_Prefix($$)
17650{
17651 my ($LibVersion, $Prefix) = @_;
17652
17653 $Prefix = lc($Prefix);
17654 $Prefix=~s/[_]+\Z//g;
17655
17656 foreach ("-2", "2", "-1", "1", "")
17657 { # libgnome-2.so
17658 # libxml2.so
17659 # libdbus-1.so
17660 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
17661 return $Path;
17662 }
17663 }
17664 return "";
17665}
17666
17667sub getPrefix($)
17668{
17669 my $Str = $_[0];
17670 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
17671 { # XmuValidArea: Xmu
17672 return $1;
17673 }
17674 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
17675 { # snfReadFont: snf
17676 return $1;
17677 }
17678 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
17679 { # XRRTimes: XRR
17680 return $1;
17681 }
17682 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
17683 { # H5HF_delete: H5
17684 return $1;
17685 }
17686 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
17687 { # alarm_event_add: alarm_
17688 return $1;
17689 }
17690 elsif($Str=~/\A(([a-z])\2{1,})/i)
17691 { # ffopen
17692 return $1;
17693 }
17694 return "";
17695}
17696
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017697sub getSymbolSize($$)
17698{ # size from the shared library
17699 my ($Symbol, $LibVersion) = @_;
17700 return 0 if(not $Symbol);
17701 if(defined $Symbol_Library{$LibVersion}{$Symbol}
17702 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
17703 {
17704 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
17705 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
17706 {
17707 if($Size<0) {
17708 return -$Size;
17709 }
17710 }
17711 }
17712 return 0;
17713}
17714
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017715sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017716{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
17717 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017718 my ($Name, $Type) = @_;
17719
17720 # single
17721 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017722 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017723 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017724 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017725 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017726
17727 # double
17728 if($Name=~/$DEFAULT_STD_PARMS/)
17729 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040017730 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017731 {
17732 my ($ShortName, $FuncParams) = split_Signature($Name);
17733
17734 foreach my $FParam (separate_Params($FuncParams, 0, 0))
17735 {
17736 if(index($FParam, "<")!=-1)
17737 {
17738 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
17739 my $FParam_N = canonifyName($FParam, "T");
17740 if($FParam_N ne $FParam) {
17741 $Name=~s/\Q$FParam\E/$FParam_N/g;
17742 }
17743 }
17744 }
17745 }
17746 elsif($Type eq "T")
17747 {
17748 my ($ShortTmpl, $TmplParams) = template_Base($Name);
17749
17750 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040017751 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017752 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040017753 my $FParam = $TParams[0];
17754 foreach my $Pos (1 .. $#TParams)
17755 {
17756 my $TParam = $TParams[$Pos];
17757 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
17758 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
17759 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017760 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017761 }
17762 }
17763 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040017764 if($Type eq "S") {
17765 return formatName($Name, "S");
17766 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017767 return $Name;
17768}
17769
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017770sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017771{
17772 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017773 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017774 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017775 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017776 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017777 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017778 next if($tr_name{$Symbol});
17779 $Symbol=~s/[\@\$]+(.*)\Z//;
17780 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017781 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017782 elsif(index($Symbol, "?")==0)
17783 {
17784 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017785 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017786 }
17787 else
17788 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017789 $tr_name{$Symbol} = $Symbol;
17790 $mangled_name_gcc{$Symbol} = $Symbol;
17791 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017792 }
17793 }
17794 if($#MnglNames1 > -1)
17795 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017796 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017797 foreach my $MnglName (@MnglNames1)
17798 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017799 if(my $Unmangled = pop(@UnmangledNames))
17800 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040017801 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017802 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
17803 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
17804 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017805 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017806 and $tr_name{$MnglName}=~/vtable for (.+)/)
17807 { # bind class name and v-table symbol
17808 my $ClassName = $1;
17809 $ClassVTable{$ClassName} = $MnglName;
17810 $VTableClass{$MnglName} = $ClassName;
17811 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017812 }
17813 }
17814 }
17815 if($#MnglNames2 > -1)
17816 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017817 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017818 foreach my $MnglName (@MnglNames2)
17819 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017820 if(my $Unmangled = pop(@UnmangledNames))
17821 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017822 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017823 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
17824 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017825 }
17826 }
17827 return \%tr_name;
17828}
17829
17830sub link_symbol($$$)
17831{
17832 my ($Symbol, $RunWith, $Deps) = @_;
17833 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
17834 return 1;
17835 }
17836 if($Deps eq "+Deps")
17837 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017838 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017839 return 1;
17840 }
17841 }
17842 return 0;
17843}
17844
17845sub link_symbol_internal($$$)
17846{
17847 my ($Symbol, $RunWith, $Where) = @_;
17848 return 0 if(not $Where or not $Symbol);
17849 if($Where->{$RunWith}{$Symbol})
17850 { # the exact match by symbol name
17851 return 1;
17852 }
17853 if(my $VSym = $SymVer{$RunWith}{$Symbol})
17854 { # indirect symbol version, i.e.
17855 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017856 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017857 if($Where->{$RunWith}{$VSym}) {
17858 return 1;
17859 }
17860 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017861 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017862 if($Sym and $Ver)
17863 { # search for the symbol with the same version
17864 # or without version
17865 if($Where->{$RunWith}{$Sym})
17866 { # old: foo@v|foo@@v
17867 # new: foo
17868 return 1;
17869 }
17870 if($Where->{$RunWith}{$Sym."\@".$Ver})
17871 { # old: foo|foo@@v
17872 # new: foo@v
17873 return 1;
17874 }
17875 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
17876 { # old: foo|foo@v
17877 # new: foo@@v
17878 return 1;
17879 }
17880 }
17881 return 0;
17882}
17883
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017884sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017885{
17886 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017887 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017888 my @Imported = ();
17889 if($OSgroup eq "macos")
17890 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017891 my $NM = get_CmdPath("nm");
17892 if(not $NM) {
17893 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017894 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017895 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017896 while(<APP>)
17897 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017898 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017899 push(@Imported, $1);
17900 }
17901 }
17902 close(APP);
17903 }
17904 elsif($OSgroup eq "windows")
17905 {
17906 my $DumpBinCmd = get_CmdPath("dumpbin");
17907 if(not $DumpBinCmd) {
17908 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
17909 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017910 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017911 while(<APP>)
17912 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017913 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
17914 push(@Imported, $1);
17915 }
17916 }
17917 close(APP);
17918 }
17919 else
17920 {
17921 my $ReadelfCmd = get_CmdPath("readelf");
17922 if(not $ReadelfCmd) {
17923 exitStatus("Not_Found", "can't find \"readelf\"");
17924 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017925 open(APP, "$ReadelfCmd -WhlSsdA \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017926 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017927 while(<APP>)
17928 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017929 if(defined $symtab)
17930 { # do nothing with symtab
17931 if(index($_, "'.dynsym'")!=-1)
17932 { # dynamic table
17933 $symtab = undef;
17934 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017935 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017936 elsif(index($_, "'.symtab'")!=-1)
17937 { # symbol table
17938 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017939 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017940 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017941 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017942 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
17943 if($Ndx eq "UND")
17944 { # only imported symbols
17945 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017946 }
17947 }
17948 }
17949 close(APP);
17950 }
17951 return @Imported;
17952}
17953
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017954my %ELF_BIND = map {$_=>1} (
17955 "WEAK",
17956 "GLOBAL"
17957);
17958
17959my %ELF_TYPE = map {$_=>1} (
17960 "FUNC",
17961 "IFUNC",
17962 "OBJECT",
17963 "COMMON"
17964);
17965
17966my %ELF_VIS = map {$_=>1} (
17967 "DEFAULT",
17968 "PROTECTED"
17969);
17970
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017971sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017972{ # read the line of 'readelf' output corresponding to the symbol
17973 my @Info = split(/\s+/, $_[0]);
17974 # Num: Value Size Type Bind Vis Ndx Name
17975 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017976 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017977 shift(@Info); # spaces
17978 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017979
17980 if($#Info==7)
17981 { # UND SYMBOL (N)
17982 if($Info[7]=~/\(\d+\)/) {
17983 pop(@Info);
17984 }
17985 }
17986
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017987 if($#Info!=6)
17988 { # other lines
17989 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017990 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017991 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017992 return () if(not defined $ELF_BIND{$Info[3]});
17993 return () if(not defined $ELF_VIS{$Info[4]});
17994 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
17995 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
17996 return ();
17997 }
17998 if($OStarget eq "symbian")
17999 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18000 if(index($Info[6], "_._.absent_export_")!=-1)
18001 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18002 return ();
18003 }
18004 $Info[6]=~s/\@.+//g; # remove version
18005 }
18006 if(index($Info[2], "0x") == 0)
18007 { # size == 0x3d158
18008 $Info[2] = hex($Info[2]);
18009 }
18010 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018011}
18012
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018013sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018014{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018015 my ($LibVersion, $Name) = @_;
18016 return "" if(not $LibVersion or not $Name);
18017 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18018 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018019 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018020 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18021}
18022
18023sub get_LibPath_I($$)
18024{
18025 my ($LibVersion, $Name) = @_;
18026 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018027 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018028 if(-f $Name)
18029 { # absolute path
18030 return $Name;
18031 }
18032 else
18033 { # broken
18034 return "";
18035 }
18036 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018037 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018038 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018039 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018040 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018041 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018042 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018043 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018044 }
18045 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18046 { # ldconfig default paths
18047 return $DefaultPath;
18048 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018049 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018050 { # search in default linker directories
18051 # and then in all system paths
18052 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018053 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018054 }
18055 }
18056 detectSystemObjects() if(not keys(%SystemObjects));
18057 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18058 return $AllObjects[0];
18059 }
18060 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18061 {
18062 if($ShortName ne $Name)
18063 { # FIXME: check this case
18064 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18065 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018066 }
18067 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018068 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018069 # can't find
18070 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018071}
18072
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018073sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018074{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018075 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18076 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018077
18078 my $Real_Path = realpath($Lib_Path);
18079
18080 if(not $Real_Path)
18081 { # broken link
18082 return ();
18083 }
18084
18085 my $Lib_Name = get_filename($Real_Path);
18086
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018087 if($ExtraInfo)
18088 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018089 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018090 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018091 }
18092
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018093 if($IsNeededLib)
18094 {
18095 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18096 return ();
18097 }
18098 }
18099 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018100 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018101
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018102 if($CheckImpl)
18103 {
18104 if(not $IsNeededLib) {
18105 getImplementations($LibVersion, $Lib_Path);
18106 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018107 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018108
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018109 push(@RecurLib, $Lib_Name);
18110 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018111 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18112
18113 if(not $IsNeededLib)
18114 { # special cases: libstdc++ and libc
18115 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18116 {
18117 if($ShortName eq "libstdc++")
18118 { # libstdc++.so.6
18119 $STDCXX_TESTING = 1;
18120 }
18121 elsif($ShortName eq "libc")
18122 { # libc-2.11.3.so
18123 $GLIBC_TESTING = 1;
18124 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018125 }
18126 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018127 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018128 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018129 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018130 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018131 mkpath(get_dirname($DebugPath));
18132 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018133 if($OStarget eq "macos")
18134 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018135 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018136 if(not $NM) {
18137 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018138 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018139 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018140 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018141 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018142 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018143 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018144 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018145 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018146 else
18147 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018148 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018149 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018150 while(<LIB>)
18151 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018152 if($CheckUndefined)
18153 {
18154 if(not $IsNeededLib)
18155 {
18156 if(/ U _([\w\$]+)\s*\Z/)
18157 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018158 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018159 next;
18160 }
18161 }
18162 }
18163
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018164 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018165 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018166 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018167 if($IsNeededLib)
18168 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018169 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018170 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018171 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18172 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018173 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018174 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018175 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018176 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018177 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18178 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018179 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18180 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018181 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018182 setLanguage($LibVersion, "C++");
18183 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018184 }
18185 if($CheckObjectsOnly
18186 and $LibVersion==1) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018187 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018188 }
18189 }
18190 }
18191 }
18192 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018193
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018194 if($Deps)
18195 {
18196 if($LIB_TYPE eq "dynamic")
18197 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018198
18199 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018200 if(not $OtoolCmd) {
18201 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018202 }
18203
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018204 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18205 while(<LIB>)
18206 {
18207 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
18208 and $1 ne $Lib_Path) {
18209 $NeededLib{$1} = 1;
18210 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018211 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018212 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018213 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018214 }
18215 }
18216 elsif($OStarget eq "windows")
18217 { # Windows *.dll, *.lib
18218 my $DumpBinCmd = get_CmdPath("dumpbin");
18219 if(not $DumpBinCmd) {
18220 exitStatus("Not_Found", "can't find \"dumpbin\"");
18221 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018222 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018223 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018224 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018225 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018226 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018227 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018228 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018229 else
18230 { # write to pipe
18231 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018232 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018233 while(<LIB>)
18234 { # 1197 4AC 0000A620 SetThreadStackGuarantee
18235 # 1198 4AD SetThreadToken (forwarded to ...)
18236 # 3368 _o2i_ECPublicKey
18237 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*\Z/i
18238 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
18239 or /\A\s*\d+\s+_([\w\?\@]+)\s*\Z/)
18240 { # dynamic, static and forwarded symbols
18241 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018242 if($IsNeededLib)
18243 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018244 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018245 {
18246 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
18247 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
18248 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018249 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018250 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018251 {
18252 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
18253 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018254 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18255 {
18256 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
18257 setLanguage($LibVersion, "C++");
18258 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018259 }
18260 if($CheckObjectsOnly
18261 and $LibVersion==1) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018262 $CheckedSymbols{"Binary"}{$realname} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018263 }
18264 }
18265 }
18266 }
18267 close(LIB);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018268 if($Deps)
18269 {
18270 if($LIB_TYPE eq "dynamic")
18271 { # dependencies
18272 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18273 while(<LIB>)
18274 {
18275 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
18276 and $1 ne $Lib_Path) {
18277 $NeededLib{path_format($1, $OSgroup)} = 1;
18278 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018279 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018280 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018281 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018282 }
18283 }
18284 else
18285 { # Unix; *.so, *.a
18286 # Symbian: *.dso, *.lib
18287 my $ReadelfCmd = get_CmdPath("readelf");
18288 if(not $ReadelfCmd) {
18289 exitStatus("Not_Found", "can't find \"readelf\"");
18290 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018291 $ReadelfCmd .= " -WhlSsdA \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
18292 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018293 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018294 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018295 system($ReadelfCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018296 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018297 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018298 else
18299 { # write to pipe
18300 open(LIB, $ReadelfCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018301 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018302 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018303 while(<LIB>)
18304 {
18305 if($LIB_TYPE eq "dynamic")
18306 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018307 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018308 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018309 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018310 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018311 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018312 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018313 # do nothing with symtab
18314 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018315 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018316 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018317 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018318 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018319 next;
18320 }
18321 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018322 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018323 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018324 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018325 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018326 if($CheckUndefined)
18327 {
18328 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018329 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018330 }
18331 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018332 next;
18333 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040018334 if($Bind eq "WEAK")
18335 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018336 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040018337 if($Weak eq "-Weak")
18338 { # skip WEAK symbols
18339 next;
18340 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018341 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018342 my $Short = $Symbol;
18343 $Short=~s/\@.+//g;
18344 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018345 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018346 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
18347 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018348 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018349 if($IsNeededLib)
18350 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018351 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018352 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018353 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18354 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018355 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018356 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018357 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018358 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018359 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18360 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
18361 if($Vers)
18362 {
18363 if($LIB_EXT eq "so")
18364 { # value
18365 $Interface_Value{$LibVersion}{$Symbol} = $Value;
18366 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
18367 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018368 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018369 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18370 {
18371 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
18372 setLanguage($LibVersion, "C++");
18373 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018374 }
18375 if($CheckObjectsOnly
18376 and $LibVersion==1) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018377 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018378 }
18379 }
18380 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018381 elsif($LIB_TYPE eq "dynamic")
18382 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018383 if($Deps)
18384 {
18385 if(/NEEDED.+\[([^\[\]]+)\]/)
18386 { # dependencies:
18387 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
18388 $NeededLib{$1} = 1;
18389 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018390 }
18391 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018392 }
18393 close(LIB);
18394 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018395 if($Vers)
18396 {
18397 if(not $IsNeededLib and $LIB_EXT eq "so")
18398 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018399 my %Found = ();
18400
18401 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018402 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018403 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018404 next if(index($Symbol,"\@")==-1);
18405 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018406 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018407 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018408 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018409 if($Symbol_SameValue ne $Symbol
18410 and index($Symbol_SameValue,"\@")==-1)
18411 {
18412 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018413 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018414 last;
18415 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018416 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018417 }
18418 }
18419
18420 # default
18421 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
18422 {
18423 next if(defined $Found{$Symbol});
18424 next if(index($Symbol,"\@\@")==-1);
18425
18426 if($Symbol=~/\A([^\@]*)\@\@/
18427 and not $SymVer{$LibVersion}{$1})
18428 {
18429 $SymVer{$LibVersion}{$1} = $Symbol;
18430 $Found{$Symbol} = 1;
18431 }
18432 }
18433
18434 # non-default
18435 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
18436 {
18437 next if(defined $Found{$Symbol});
18438 next if(index($Symbol,"\@")==-1);
18439
18440 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
18441 and not $SymVer{$LibVersion}{$1})
18442 {
18443 $SymVer{$LibVersion}{$1} = $Symbol;
18444 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018445 }
18446 }
18447 }
18448 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018449 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018450 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018451 foreach my $DyLib (sort keys(%NeededLib))
18452 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018453 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
18454
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018455 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
18456 {
18457 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
18458 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
18459 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018460 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018461 }
18462 }
18463 pop(@RecurLib);
18464 return $Library_Symbol{$LibVersion};
18465}
18466
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018467sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018468{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018469 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018470 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018471 return keys(%Prefixes);
18472}
18473
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018474sub get_prefixes_I($$)
18475{
18476 foreach my $P (@{$_[0]})
18477 {
18478 my @Parts = reverse(split(/[\/\\]+/, $P));
18479 my $Name = $Parts[0];
18480 foreach (1 .. $#Parts)
18481 {
18482 $_[1]->{$Name}{$P} = 1;
18483 last if($_>4 or $Parts[$_] eq "include");
18484 $Name = $Parts[$_].$SLASH.$Name;
18485 }
18486 }
18487}
18488
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018489sub detectSystemHeaders()
18490{
18491 my @SysHeaders = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018492 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018493 {
18494 next if(not -d $DevelPath);
18495 # search for all header files in the /usr/include
18496 # with or without extension (ncurses.h, QtCore, ...)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018497 push(@SysHeaders, cmd_find($DevelPath,"f"));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018498 foreach my $Link (cmd_find($DevelPath,"l"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018499 { # add symbolic links
18500 if(-f $Link) {
18501 push(@SysHeaders, $Link);
18502 }
18503 }
18504 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018505 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018506 { # search for config headers in the /usr/lib
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018507 next if(not -d $DevelPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018508 foreach (cmd_find($DevelPath,"f",'\.h(pp|xx)?\Z|\/include\/',"",1))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018509 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018510 if(/\/(gcc|jvm|syslinux|kbd|parrot|xemacs)/)
18511 { # skip useless headers
18512 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018513 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018514 push(@SysHeaders, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018515 }
18516 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018517 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018518}
18519
18520sub detectSystemObjects()
18521{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018522 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018523 {
18524 next if(not -d $DevelPath);
18525 foreach my $Path (find_libs($DevelPath,"",""))
18526 { # search for shared libraries in the /usr/lib (including symbolic links)
18527 $SystemObjects{parse_libname(get_filename($Path), "name+ext", $OStarget)}{$Path}=1;
18528 }
18529 }
18530}
18531
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018532sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018533{
18534 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018535 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018536 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
18537 {
18538 if(not -e $Dest) {
18539 exitStatus("Access_Error", "can't access \'$Dest\'");
18540 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018541 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018542 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
18543 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018544 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018545 }
18546 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018547 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018548}
18549
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018550sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018551{
18552 my ($Path, $LibVersion) = @_;
18553 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018554 my $Name = get_filename($Path);
18555 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018556 return 1;
18557 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018558 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018559 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
18560 return 1;
18561 }
18562 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
18563 {
18564 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
18565 return 1;
18566 }
18567 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018568 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018569 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018570 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018571 return 1;
18572 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018573 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018574 return 1;
18575 }
18576 }
18577 return 0;
18578}
18579
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018580sub specificHeader($$)
18581{
18582 my ($Header, $Spec) = @_;
18583 my $Name = get_filename($Header);
18584
18585 if($Spec eq "windows")
18586 {# MS Windows
18587 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
18588 return 1 if($Name=~/([._-]w|win)(32|64)/i);
18589 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
18590 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
18591 my @Dirs = (
18592 "win32",
18593 "win64",
18594 "win",
18595 "windows",
18596 "msvcrt"
18597 ); # /gsf-win32/
18598 if(my $DIRs = join("|", @Dirs)) {
18599 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
18600 }
18601 }
18602 elsif($Spec eq "macos")
18603 { # Mac OS
18604 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
18605 }
18606
18607 return 0;
18608}
18609
18610sub skipAlienHeader($)
18611{
18612 my $Path = $_[0];
18613 my $Name = get_filename($Path);
18614 my $Dir = get_dirname($Path);
18615
18616 if($Tolerance=~/2/)
18617 { # 2 - skip internal headers
18618 my @Terms = (
18619 "p",
18620 "priv",
18621 "int",
18622 "impl",
18623 "implementation",
18624 "internal",
18625 "private",
18626 "old",
18627 "compat",
18628 "debug",
18629 "test",
18630 "gen"
18631 );
18632
18633 my @Dirs = (
18634 "private",
18635 "priv",
18636 "port",
18637 "impl",
18638 "internal",
18639 "detail",
18640 "details",
18641 "old",
18642 "compat",
18643 "debug",
18644 "config",
18645 "compiler",
18646 "platform",
18647 "test"
18648 );
18649
18650 if(my $TERMs = join("|", @Terms)) {
18651 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
18652 }
18653 if(my $DIRs = join("|", @Dirs)) {
18654 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
18655 }
18656
18657 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
18658 }
18659
18660 if($Tolerance=~/1/)
18661 { # 1 - skip non-Linux headers
18662 if($OSgroup ne "windows")
18663 {
18664 if(specificHeader($Path, "windows")) {
18665 return 1;
18666 }
18667 }
18668 if($OSgroup ne "macos")
18669 {
18670 if(specificHeader($Path, "macos")) {
18671 return 1;
18672 }
18673 }
18674 }
18675
18676 # valid
18677 return 0;
18678}
18679
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018680sub skipHeader($$)
18681{
18682 my ($Path, $LibVersion) = @_;
18683 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018684 if(defined $Cache{"skipHeader"}{$Path}) {
18685 return $Cache{"skipHeader"}{$Path};
18686 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018687 if(defined $Tolerance and $Tolerance=~/1|2/)
18688 { # --tolerant
18689 if(skipAlienHeader($Path)) {
18690 return ($Cache{"skipHeader"}{$Path} = 1);
18691 }
18692 }
18693 if(not keys(%{$SkipHeaders{$LibVersion}})) {
18694 return 0;
18695 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018696 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
18697}
18698
18699sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018700{ # returns:
18701 # 1 - if header should NOT be included and checked
18702 # 2 - if header should NOT be included, but should be checked
18703 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018704 my $Name = get_filename($Path);
18705 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018706 return $Kind;
18707 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018708 foreach my $D (keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018709 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018710 if(index($Path, $D)!=-1)
18711 {
18712 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
18713 return $SkipHeaders{$LibVersion}{"Path"}{$D};
18714 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018715 }
18716 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018717 foreach my $P (keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018718 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018719 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
18720 {
18721 if($Name=~/$P/) {
18722 return $Kind;
18723 }
18724 if($P=~/[\/\\]/ and $Path=~/$P/) {
18725 return $Kind;
18726 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018727 }
18728 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018729
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018730 return 0;
18731}
18732
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018733sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018734{
18735 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018736 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018737 { # system directory
18738 return;
18739 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018740 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018741 { # already registered
18742 return;
18743 }
18744 foreach my $Path (find_libs($Dir,"",1))
18745 {
18746 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018747 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018748 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018749 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018750 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
18751}
18752
18753sub registerObject($$)
18754{
18755 my ($Path, $LibVersion) = @_;
18756 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018757 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko27681702012-11-12 16:33:39 +040018758 if($OSgroup=~/linux|bsd/i)
18759 {
18760 if(my $SONAME = getSONAME($Path)) {
18761 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
18762 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018763 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018764 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
18765 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018766 }
18767}
18768
18769sub getSONAME($)
18770{
18771 my $Path = $_[0];
18772 return if(not $Path);
18773 if(defined $Cache{"getSONAME"}{$Path}) {
18774 return $Cache{"getSONAME"}{$Path};
18775 }
18776 my $ObjdumpCmd = get_CmdPath("objdump");
18777 if(not $ObjdumpCmd) {
18778 exitStatus("Not_Found", "can't find \"objdump\"");
18779 }
18780 my $SonameCmd = "$ObjdumpCmd -x $Path 2>$TMP_DIR/null";
18781 if($OSgroup eq "windows") {
18782 $SonameCmd .= " | find \"SONAME\"";
18783 }
18784 else {
18785 $SonameCmd .= " | grep SONAME";
18786 }
18787 if(my $SonameInfo = `$SonameCmd`) {
18788 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
18789 return ($Cache{"getSONAME"}{$Path} = $1);
18790 }
18791 }
18792 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018793}
18794
18795sub getSOPaths_Dest($$)
18796{
18797 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018798 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018799 return ();
18800 }
18801 if(-f $Dest)
18802 {
18803 if(not parse_libname($Dest, "name", $OStarget)) {
18804 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
18805 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018806 registerObject($Dest, $LibVersion);
18807 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018808 return ($Dest);
18809 }
18810 elsif(-d $Dest)
18811 {
18812 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018813 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018814 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018815 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
18816 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018817 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018818 { # all files and symlinks that match the name of a library
18819 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
18820 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018821 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018822 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018823 }
18824 }
18825 }
18826 else
18827 { # search for all files and symlinks
18828 foreach my $Path (find_libs($Dest,"",""))
18829 {
18830 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018831 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018832 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018833 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018834 }
18835 if($OSgroup eq "macos")
18836 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018837 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018838 {
18839 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018840 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018841 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018842 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
18843 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018844 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018845 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018846 }
18847 }
18848 }
18849 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018850 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018851 }
18852 else {
18853 return ();
18854 }
18855}
18856
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018857sub isCyclical($$)
18858{
18859 my ($Stack, $Value) = @_;
18860 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018861}
18862
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018863sub detectWordSize()
18864{
18865 return "" if(not $GCC_PATH);
18866 if($Cache{"detectWordSize"}) {
18867 return $Cache{"detectWordSize"};
18868 }
18869 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018870 my $Defines = `$GCC_PATH -E -dD \"$TMP_DIR/empty.h\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018871 unlink("$TMP_DIR/empty.h");
18872 my $WSize = 0;
18873 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018874 { # GCC 4
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018875 $WSize = $1;
18876 }
18877 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018878 { # GCC 3
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018879 my $PTRDIFF = $1;
18880 if($PTRDIFF=~/long/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018881 $WSize = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018882 }
18883 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018884 $WSize = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018885 }
18886 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018887 if(not $WSize) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018888 exitStatus("Error", "can't check WORD size");
18889 }
18890 return ($Cache{"detectWordSize"} = $WSize);
18891}
18892
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040018893sub getWordSize($) {
18894 return $WORD_SIZE{$_[0]};
18895}
18896
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018897sub majorVersion($)
18898{
18899 my $V = $_[0];
18900 return 0 if(not $V);
18901 my @VParts = split(/\./, $V);
18902 return $VParts[0];
18903}
18904
18905sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018906{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018907 my ($V1, $V2) = @_;
18908 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018909 my @V1Parts = split(/\./, $V1);
18910 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018911 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
18912 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018913 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
18914 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
18915 }
18916 return -1 if($#V1Parts < $#V2Parts);
18917 return 1 if($#V1Parts > $#V2Parts);
18918 return 0;
18919}
18920
18921sub read_ABI_Dump($$)
18922{
18923 my ($LibVersion, $Path) = @_;
18924 return if(not $LibVersion or not -e $Path);
18925 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018926 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018927 { # input *.abi
18928 $FilePath = $Path;
18929 }
18930 else
18931 { # input *.abi.tar.gz
18932 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018933 if(not isDump_U($FilePath)) {
18934 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
18935 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018936 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018937
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018938 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040018939
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018940 my $Line = readLineNum($FilePath, 0);
18941 if($Line=~/xml/)
18942 { # XML format
18943 loadModule("XmlDump");
18944 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018945 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018946 else
18947 { # Perl Data::Dumper format (default)
18948 open(DUMP, $FilePath);
18949 local $/ = undef;
18950 my $Content = <DUMP>;
18951 close(DUMP);
18952
18953 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
18954 { # remove temp file
18955 unlink($FilePath);
18956 }
18957 if($Content!~/};\s*\Z/) {
18958 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
18959 }
18960 $ABI = eval($Content);
18961 if(not $ABI) {
18962 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
18963 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018964 }
18965 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018966 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018967 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018968 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018969 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018970 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018971 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018972 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018973
18974 if($ABI->{"ABI_DUMP_VERSION"})
18975 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018976 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018977 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018978 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018979 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018980 }
18981 else
18982 { # support for old ABI dumps
18983 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018984 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018985 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018986 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018987 }
18988 if(majorVersion($DVersion)<2)
18989 { # support for old ABI dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018990 if($UseOldDumps)
18991 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018992 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)<0) {
18993 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (older than $OLDEST_SUPPORTED_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018994 }
18995 }
18996 else
18997 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018998 my $Msg = "incompatible version \'$DVersion\' of specified ABI dump (allowed only 2.0<=V<=$ABI_DUMP_VERSION)";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018999 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)>=0) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019000 $Msg .= "\nUse -old-dumps option to use old-version dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019001 }
19002 exitStatus("Dump_Version", $Msg);
19003 }
19004 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019005
19006 if(defined $ABI->{"ABI_DUMPER_VERSION"})
19007 { # DWARF ABI Dump
19008 $UseConv_Real{$LibVersion}{"P"} = 1;
19009 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19010
19011 $UsedDump{$LibVersion}{"DWARF"} = 1;
19012
19013 $TargetComponent = "module";
19014 }
19015
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019016 if(not checkDump($LibVersion, "2.11"))
19017 { # old ABI dumps
19018 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019019 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019020 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019021 { # ABI dump created with --binary option
19022 $UsedDump{$LibVersion}{"BinOnly"} = 1;
19023 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019024 else
19025 { # default
19026 $UsedDump{$LibVersion}{"SrcBin"} = 1;
19027 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019028
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019029 if(defined $ABI->{"Mode"}
19030 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019031 { # --ext option
19032 $ExtendedCheck = 1;
19033 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019034 if($ABI->{"Extra"}) {
19035 $ExtraDump = 1;
19036 }
19037
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019038 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019039 {
19040 $UsedDump{$LibVersion}{"L"} = $Lang;
19041 setLanguage($LibVersion, $Lang);
19042 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019043 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019044 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019045 }
19046 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019047 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019048 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019049 if(not $TInfo)
19050 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019051 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019052 }
19053 my %Tid_TDid = ();
19054 foreach my $TDid (keys(%{$TInfo}))
19055 {
19056 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
19057 {
19058 $MAX_ID = $Tid if($Tid>$MAX_ID);
19059 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
19060 $Tid_TDid{$Tid}{$TDid}=1;
19061 }
19062 }
19063 my %NewID = ();
19064 foreach my $Tid (keys(%Tid_TDid))
19065 {
19066 my @TDids = keys(%{$Tid_TDid{$Tid}});
19067 if($#TDids>=1)
19068 {
19069 foreach my $TDid (@TDids)
19070 {
19071 if($TDid) {
19072 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19073 }
19074 else
19075 {
19076 if(my $ID = ++$MAX_ID)
19077 {
19078 $NewID{$TDid}{$Tid} = $ID;
19079 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
19080 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
19081 }
19082 }
19083 }
19084 }
19085 else
19086 {
19087 my $TDid = $TDids[0];
19088 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19089 }
19090 }
19091 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
19092 {
19093 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
19094 if(defined $Info{"BaseType"})
19095 {
19096 my $Bid = $Info{"BaseType"}{"Tid"};
19097 my $BDid = $Info{"BaseType"}{"TDid"};
19098 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019099 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019100 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
19101 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
19102 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019103 }
19104 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
19105 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019106 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019107 read_Machine_DumpInfo($ABI, $LibVersion);
19108 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019109 if(not $SymbolInfo{$LibVersion})
19110 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019111 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019112 }
19113 if(not keys(%{$SymbolInfo{$LibVersion}}))
19114 { # validation of old-version dumps
19115 if(not $ExtendedCheck) {
19116 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
19117 }
19118 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019119 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019120 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019121 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019122 else
19123 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019124 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019125 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019126 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019127 }
19128 if(not $DepSymbols)
19129 { # Cannot reconstruct DepSymbols. This may result in false
19130 # positives if the old dump is for library 2. Not a problem if
19131 # old dumps are only from old libraries.
19132 $DepSymbols = {};
19133 }
19134 foreach my $Symbol (keys(%{$DepSymbols})) {
19135 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
19136 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019137 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019138 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
19139 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
19140 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019141 if(not $SkipTypes{$LibVersion})
19142 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019143 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019144 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019145 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019146 if(not $SkipSymbols{$LibVersion})
19147 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019148 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019149 }
19150 if(not $SkipSymbols{$LibVersion})
19151 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019152 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019153 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019154 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
19155 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
19156 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019157 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019158 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019159 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019160 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019161 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019162 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019163 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019164 if(not checkDump($LibVersion, "2.10.1")
19165 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019166 { # support for old ABI dumps: added target headers
19167 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
19168 $TargetHeaders{$LibVersion}{get_filename($_)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019169 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019170 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
19171 $TargetHeaders{$LibVersion}{get_filename($_)}=1;
19172 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019173 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019174 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019175 if(defined $ABI->{"GccConstants"})
19176 { # 3.0
19177 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
19178 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
19179 }
19180 }
19181
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019182 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019183 if(not $NestedNameSpaces{$LibVersion})
19184 { # support for old dumps
19185 # Cannot reconstruct NameSpaces. This may affect design
19186 # of the compatibility report.
19187 $NestedNameSpaces{$LibVersion} = {};
19188 }
19189 # target system type
19190 # needed to adopt HTML report
19191 if(not $DumpSystem)
19192 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019193 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019194 }
19195 # recreate environment
19196 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
19197 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019198 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019199 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019200 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19201 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019202 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019203 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019204 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019205 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19206 {
19207 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19208 setLanguage($LibVersion, "C++");
19209 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019210 }
19211 }
19212 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019213 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
19214 {
19215 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
19216 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19217 }
19218 }
19219
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019220 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019221 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019222 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019223 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019224 {
19225 if(not $Symbol_Library{$LibVersion}{$MnglName}
19226 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
19227 push(@VFunc, $MnglName);
19228 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019229 }
19230 }
19231 translateSymbols(@VFunc, $LibVersion);
19232 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019233 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
19234
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019235 if(not checkDump($LibVersion, "3.0"))
19236 { # support for old ABI dumps
19237 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
19238 {
19239 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
19240 {
19241 if(ref($BaseType) eq "HASH") {
19242 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
19243 }
19244 }
19245 }
19246 }
19247
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019248 if(not checkDump($LibVersion, "2.20"))
19249 { # support for old ABI dumps
19250 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
19251 {
19252 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
19253
19254 if($TType=~/Struct|Union|Enum|Typedef/)
19255 { # repair complex types first
19256 next;
19257 }
19258
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019259 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019260 {
19261 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
19262 if($BType=~/Struct|Union|Enum/i)
19263 {
19264 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
19265 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
19266 }
19267 }
19268 }
19269 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
19270 {
19271 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
19272 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
19273 if($TType=~/Struct|Union|Enum/) {
19274 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
19275 }
19276 }
19277 }
19278
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019279 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019280 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019281 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
19282 { # support for old ABI dumps < 2.0 (ACC 1.22)
19283 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
19284 {
19285 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
19286 {
19287 if($Access ne "public") {
19288 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
19289 }
19290 }
19291 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
19292 }
19293 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
19294 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019295 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
19296 { # support for old ABI dumps
19297 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
19298 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019299 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
19300 { # DWARF ABI Dumps
19301 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
19302 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019303 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
19304 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
19305 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019306 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
19307 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019308 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019309 foreach (keys(%{$TInfo{"Base"}})) {
19310 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019311 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019312 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019313 if($TInfo{"Type"} eq "MethodPtr")
19314 {
19315 if(defined $TInfo{"Param"})
19316 { # support for old ABI dumps <= 1.17
19317 if(not defined $TInfo{"Param"}{"0"})
19318 {
19319 my $Max = keys(%{$TInfo{"Param"}});
19320 foreach my $Pos (1 .. $Max) {
19321 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
19322 }
19323 delete($TInfo{"Param"}{$Max});
19324 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
19325 }
19326 }
19327 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019328 if($TInfo{"BaseType"} eq $TypeId)
19329 { # fix ABI dump
19330 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
19331 }
19332 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019333 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019334 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019335 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019336 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
19337 if(not $BName)
19338 { # broken type
19339 next;
19340 }
19341 if($TInfo{"Name"} eq $BName)
19342 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019343 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019344 next;
19345 }
19346 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
19347 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019348 }
19349 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019350 }
19351 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
19352 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019353 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019354 }
19355 }
19356
19357 if(not checkDump($LibVersion, "2.15"))
19358 { # support for old ABI dumps
19359 my %Dups = ();
19360 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
19361 {
19362 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019363 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019364 if(not defined $TypeInfo{$LibVersion}{$ClassId})
19365 { # remove template decls
19366 delete($SymbolInfo{$LibVersion}{$InfoId});
19367 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019368 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019369 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040019370 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
19371 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019372 { # templates
19373 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019374 }
19375 }
19376 }
19377
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019378 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
19379 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040019380 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
19381 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
19382 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
19383 { # support for old ABI dumps (< 3.1)
19384 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
19385 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
19386 { # add "this" first parameter
19387 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
19388 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
19389
19390 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
19391 {
19392 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
19393 foreach my $Pos (reverse(0 .. $#Pos)) {
19394 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
19395 }
19396 }
19397 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
19398 }
19399 }
19400
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019401 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
19402 { # ABI dumps have no mangled names for C-functions
19403 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
19404 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019405 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
19406 { # support for old ABI dumps
19407 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
19408 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019409 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
19410 { # DWARF ABI Dumps
19411 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
19412 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019413 }
19414
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019415 $Descriptor{$LibVersion}{"Dump"} = 1;
19416}
19417
19418sub read_Machine_DumpInfo($$)
19419{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019420 my ($ABI, $LibVersion) = @_;
19421 if($ABI->{"Arch"}) {
19422 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019423 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019424 if($ABI->{"WordSize"}) {
19425 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019426 }
19427 else
19428 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019429 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019430 }
19431 if(not $WORD_SIZE{$LibVersion})
19432 { # support for old dumps (<1.23)
19433 if(my $Tid = getTypeIdByName("char*", $LibVersion))
19434 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019435 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019436 }
19437 else
19438 {
19439 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019440 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019441 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019442 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
19443 { # any "pointer"-type
19444 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019445 last;
19446 }
19447 }
19448 if($PSize)
19449 { # a pointer type size
19450 $WORD_SIZE{$LibVersion} = $PSize;
19451 }
19452 else {
19453 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
19454 }
19455 }
19456 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019457 if($ABI->{"GccVersion"}) {
19458 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019459 }
19460}
19461
19462sub read_Libs_DumpInfo($$)
19463{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019464 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019465 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
19466 if(not $Library_Symbol{$LibVersion})
19467 { # support for old dumps
19468 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
19469 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019470 if(keys(%{$Library_Symbol{$LibVersion}})
19471 and not $DumpAPI) {
19472 $Descriptor{$LibVersion}{"Libs"} = "OK";
19473 }
19474}
19475
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019476sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019477{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019478 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019479
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019480 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019481 and not $DumpAPI) {
19482 $Descriptor{$LibVersion}{"Headers"} = "OK";
19483 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019484 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019485 { # headers info is stored in the old dumps in the different way
19486 if($UseOldDumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019487 and my $Name = $ABI->{"Headers"}{$Identity}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019488 { # support for old dumps: headers info corrected in 1.22
19489 $Identity = $Name;
19490 }
19491 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019492 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019493 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019494
19495 if(keys(%{$ABI->{"Sources"}})
19496 and not $DumpAPI) {
19497 $Descriptor{$LibVersion}{"Sources"} = "OK";
19498 }
19499 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
19500 { # headers info is stored in the old dumps in the different way
19501 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
19502 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
19503 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019504}
19505
19506sub find_libs($$$)
19507{
19508 my ($Path, $Type, $MaxDepth) = @_;
19509 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019510 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019511}
19512
19513sub createDescriptor($$)
19514{
19515 my ($LibVersion, $Path) = @_;
19516 if(not $LibVersion or not $Path
19517 or not -e $Path) {
19518 return "";
19519 }
19520 if(-d $Path)
19521 { # directory with headers files and shared objects
19522 return "
19523 <version>
19524 ".$TargetVersion{$LibVersion}."
19525 </version>
19526
19527 <headers>
19528 $Path
19529 </headers>
19530
19531 <libs>
19532 $Path
19533 </libs>";
19534 }
19535 else
19536 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019537 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019538 { # standard XML-descriptor
19539 return readFile($Path);
19540 }
19541 elsif(is_header($Path, 2, $LibVersion))
19542 { # header file
19543 return "
19544 <version>
19545 ".$TargetVersion{$LibVersion}."
19546 </version>
19547
19548 <headers>
19549 $Path
19550 </headers>
19551
19552 <libs>
19553 none
19554 </libs>";
19555 }
19556 elsif(parse_libname($Path, "name", $OStarget))
19557 { # shared object
19558 return "
19559 <version>
19560 ".$TargetVersion{$LibVersion}."
19561 </version>
19562
19563 <headers>
19564 none
19565 </headers>
19566
19567 <libs>
19568 $Path
19569 </libs>";
19570 }
19571 else
19572 { # standard XML-descriptor
19573 return readFile($Path);
19574 }
19575 }
19576}
19577
19578sub detect_lib_default_paths()
19579{
19580 my %LPaths = ();
19581 if($OSgroup eq "bsd")
19582 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019583 if(my $LdConfig = get_CmdPath("ldconfig"))
19584 {
19585 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
19586 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019587 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
19588 {
19589 my $Name = "lib".$1;
19590 if(not defined $LPaths{$Name}) {
19591 $LPaths{$Name} = $2;
19592 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019593 }
19594 }
19595 }
19596 else {
19597 printMsg("WARNING", "can't find ldconfig");
19598 }
19599 }
19600 else
19601 {
19602 if(my $LdConfig = get_CmdPath("ldconfig"))
19603 {
19604 if($SystemRoot and $OSgroup eq "linux")
19605 { # use host (x86) ldconfig with the target (arm) ld.so.conf
19606 if(-e $SystemRoot."/etc/ld.so.conf") {
19607 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
19608 }
19609 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019610 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
19611 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019612 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
19613 {
19614 my ($Name, $Path) = ($1, $2);
19615 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019616 if(not defined $LPaths{$Name})
19617 { # get first element from the list of available paths
19618
19619 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
19620 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
19621 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
19622
19623 $LPaths{$Name} = $Path;
19624 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019625 }
19626 }
19627 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040019628 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019629 printMsg("WARNING", "can't find ldconfig");
19630 }
19631 }
19632 return \%LPaths;
19633}
19634
19635sub detect_bin_default_paths()
19636{
19637 my $EnvPaths = $ENV{"PATH"};
19638 if($OSgroup eq "beos") {
19639 $EnvPaths.=":".$ENV{"BETOOLS"};
19640 }
19641 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019642 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019643 {
19644 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019645 next if(not $Path);
19646 if($SystemRoot
19647 and $Path=~/\A\Q$SystemRoot\E\//)
19648 { # do NOT use binaries from target system
19649 next;
19650 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019651 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019652 }
19653}
19654
19655sub detect_inc_default_paths()
19656{
19657 return () if(not $GCC_PATH);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019658 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019659 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019660 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019661 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019662 next if(index($Line, "/cc1plus ")!=-1);
19663
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019664 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
19665 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019666 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019667 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019668 if(index($Path, "c++")!=-1
19669 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019670 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019671 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019672 if(not defined $MAIN_CPP_DIR
19673 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
19674 $MAIN_CPP_DIR = $Path;
19675 }
19676 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019677 elsif(index($Path, "gcc")!=-1) {
19678 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019679 }
19680 else
19681 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019682 if($Path=~/local[\/\\]+include/)
19683 { # local paths
19684 next;
19685 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019686 if($SystemRoot
19687 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
19688 { # The GCC include path for user headers is not a part of the system root
19689 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
19690 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
19691 next;
19692 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019693 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019694 }
19695 }
19696 }
19697 unlink("$TMP_DIR/empty.h");
19698 return %DPaths;
19699}
19700
19701sub detect_default_paths($)
19702{
19703 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
19704 my $Search = $_[0];
19705 if($Search!~/inc/) {
19706 $HSearch = 0;
19707 }
19708 if($Search!~/lib/) {
19709 $LSearch = 0;
19710 }
19711 if($Search!~/bin/) {
19712 $BSearch = 0;
19713 }
19714 if($Search!~/gcc/) {
19715 $GSearch = 0;
19716 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019717 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019718 { # <search_headers> section of the XML descriptor
19719 # do NOT search for systems headers
19720 $HSearch = 0;
19721 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019722 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019723 { # <search_headers> section of the XML descriptor
19724 # do NOT search for systems headers
19725 $LSearch = 0;
19726 }
19727 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
19728 { # additional search paths
19729 next if($Type eq "include" and not $HSearch);
19730 next if($Type eq "lib" and not $LSearch);
19731 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019732 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019733 }
19734 if($OSgroup ne "windows")
19735 { # unix-like
19736 foreach my $Type ("include", "lib", "bin")
19737 { # automatic detection of system "devel" directories
19738 next if($Type eq "include" and not $HSearch);
19739 next if($Type eq "lib" and not $LSearch);
19740 next if($Type eq "bin" and not $BSearch);
19741 my ($UsrDir, $RootDir) = ("/usr", "/");
19742 if($SystemRoot and $Type ne "bin")
19743 { # 1. search for target headers and libraries
19744 # 2. use host commands: ldconfig, readelf, etc.
19745 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
19746 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019747 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019748 if(-d $RootDir."/".$Type)
19749 { # if "/lib" is symbolic link
19750 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019751 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019752 }
19753 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019754 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019755 }
19756 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019757 if(-d $UsrDir)
19758 {
19759 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019760 if(-d $UsrDir."/".$Type)
19761 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019762 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019763 }
19764 }
19765 }
19766 }
19767 if($BSearch)
19768 {
19769 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019770 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019771 }
19772 # check environment variables
19773 if($OSgroup eq "beos")
19774 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019775 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019776 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019777 if($_ eq ".") {
19778 next;
19779 }
19780 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
19781 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
19782 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019783 }
19784 }
19785 if($HSearch)
19786 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019787 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
19788 split(/:|;/, $ENV{"BEINCLUDES"})
19789 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019790 }
19791 if($LSearch)
19792 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019793 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
19794 split(/:|;/, $ENV{"BELIBRARIES"}),
19795 split(/:|;/, $ENV{"LIBRARY_PATH"})
19796 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019797 }
19798 }
19799 if($LSearch)
19800 { # using linker to get system paths
19801 if(my $LPaths = detect_lib_default_paths())
19802 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019803 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019804 foreach my $Name (keys(%{$LPaths}))
19805 {
19806 if($SystemRoot
19807 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
19808 { # wrong ldconfig configuration
19809 # check your <sysroot>/etc/ld.so.conf
19810 next;
19811 }
19812 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019813 if(my $Dir = get_dirname($LPaths->{$Name})) {
19814 $Dirs{$Dir} = 1;
19815 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019816 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019817 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019818 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019819 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019820 }
19821 if($BSearch)
19822 {
19823 if($CrossGcc)
19824 { # --cross-gcc=arm-linux-gcc
19825 if(-e $CrossGcc)
19826 { # absolute or relative path
19827 $GCC_PATH = get_abs_path($CrossGcc);
19828 }
19829 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
19830 { # command name
19831 $GCC_PATH = $CrossGcc;
19832 }
19833 else {
19834 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
19835 }
19836 if($GCC_PATH=~/\s/) {
19837 $GCC_PATH = "\"".$GCC_PATH."\"";
19838 }
19839 }
19840 }
19841 if($GSearch)
19842 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019843 if(not $CrossGcc)
19844 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019845 $GCC_PATH = get_CmdPath("gcc");
19846 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019847 if(not $GCC_PATH)
19848 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019849 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019850 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019851 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019852 { # select the latest version
19853 @GCCs = sort {$b cmp $a} @GCCs;
19854 if(check_gcc($GCCs[0], "3"))
19855 {
19856 $GCC_PATH = $GCCs[0];
19857 last;
19858 }
19859 }
19860 }
19861 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019862 if(not $GCC_PATH) {
19863 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
19864 }
19865 if(not $CheckObjectsOnly_Opt)
19866 {
19867 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
19868 {
19869 my $GccTarget = get_dumpmachine($GCC_PATH);
19870 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget)");
19871 if($GccTarget=~/symbian/)
19872 {
19873 $OStarget = "symbian";
19874 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
19875 }
19876 }
19877 else {
19878 exitStatus("Error", "something is going wrong with the GCC compiler");
19879 }
19880 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019881 if($HSearch)
19882 {
19883 if(not $NoStdInc)
19884 { # do NOT search in GCC standard paths
19885 my %DPaths = detect_inc_default_paths();
19886 @DefaultCppPaths = @{$DPaths{"Cpp"}};
19887 @DefaultGccPaths = @{$DPaths{"Gcc"}};
19888 @DefaultIncPaths = @{$DPaths{"Inc"}};
19889 push_U($SystemPaths{"include"}, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019890 }
19891 }
19892 }
19893 if($HSearch)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019894 { # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019895 my $IncPath = "/usr/include";
19896 if($SystemRoot) {
19897 $IncPath = $SystemRoot.$IncPath;
19898 }
19899 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019900 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019901 }
19902 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019903
19904 if($ExtraInfo)
19905 {
19906 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
19907 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
19908 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019909}
19910
19911sub getLIB_EXT($)
19912{
19913 my $Target = $_[0];
19914 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
19915 return $Ext;
19916 }
19917 return $OS_LibExt{$LIB_TYPE}{"default"};
19918}
19919
19920sub getAR_EXT($)
19921{
19922 my $Target = $_[0];
19923 if(my $Ext = $OS_Archive{$Target}) {
19924 return $Ext;
19925 }
19926 return $OS_Archive{"default"};
19927}
19928
19929sub get_dumpversion($)
19930{
19931 my $Cmd = $_[0];
19932 return "" if(not $Cmd);
19933 if($Cache{"get_dumpversion"}{$Cmd}) {
19934 return $Cache{"get_dumpversion"}{$Cmd};
19935 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019936 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019937 chomp($V);
19938 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
19939}
19940
19941sub get_dumpmachine($)
19942{
19943 my $Cmd = $_[0];
19944 return "" if(not $Cmd);
19945 if($Cache{"get_dumpmachine"}{$Cmd}) {
19946 return $Cache{"get_dumpmachine"}{$Cmd};
19947 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019948 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019949 chomp($Machine);
19950 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
19951}
19952
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019953sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019954{
19955 my $Cmd = $_[0];
19956 return "" if(not $Cmd);
19957 my @Options = (
19958 "--version",
19959 "-help"
19960 );
19961 foreach my $Opt (@Options)
19962 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019963 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019964 if($Info) {
19965 return 1;
19966 }
19967 }
19968 return 0;
19969}
19970
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019971sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019972{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019973 my ($Cmd, $ReqVer) = @_;
19974 return 0 if(not $Cmd or not $ReqVer);
19975 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
19976 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019977 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019978 if(my $GccVer = get_dumpversion($Cmd))
19979 {
19980 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
19981 if(cmpVersions($GccVer, $ReqVer)>=0) {
19982 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
19983 }
19984 }
19985 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019986}
19987
19988sub get_depth($)
19989{
19990 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019991 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019992 }
19993 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
19994}
19995
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019996sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019997{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019998 return if($Cache{"registerGccHeaders"}); # this function should be called once
19999
20000 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020001 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020002 my @Headers = cmd_find($Path,"f");
20003 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20004 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020005 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020006 my $FileName = get_filename($HPath);
20007 if(not defined $DefaultGccHeader{$FileName})
20008 { # skip duplicated
20009 $DefaultGccHeader{$FileName} = $HPath;
20010 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020011 }
20012 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020013 $Cache{"registerGccHeaders"} = 1;
20014}
20015
20016sub registerCppHeaders()
20017{
20018 return if($Cache{"registerCppHeaders"}); # this function should be called once
20019
20020 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020021 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020022 my @Headers = cmd_find($CppDir,"f");
20023 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20024 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020025 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020026 my $FileName = get_filename($Path);
20027 if(not defined $DefaultCppHeader{$FileName})
20028 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020029 $DefaultCppHeader{$FileName} = $Path;
20030 }
20031 }
20032 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020033 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020034}
20035
20036sub parse_libname($$$)
20037{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020038 return "" if(not $_[0]);
20039 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
20040 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020041 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020042 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
20043}
20044
20045sub parse_libname_I($$$)
20046{
20047 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020048
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020049 if($Target eq "symbian") {
20050 return parse_libname_symbian($Name, $Type);
20051 }
20052 elsif($Target eq "windows") {
20053 return parse_libname_windows($Name, $Type);
20054 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020055
20056 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020057 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020058 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020059 { # libSDL-1.2.so.0.7.1
20060 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020061 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020062 if($Type eq "name")
20063 { # libSDL-1.2
20064 # libwbxml2
20065 return $2;
20066 }
20067 elsif($Type eq "name+ext")
20068 { # libSDL-1.2.so
20069 # libwbxml2.so
20070 return $1;
20071 }
20072 elsif($Type eq "version")
20073 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020074 if(defined $7
20075 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020076 { # 0.7.1
20077 return $7;
20078 }
20079 else
20080 { # libc-2.5.so (=>2.5 version)
20081 my $MV = $5;
20082 $MV=~s/\A[\-\_]+//g;
20083 return $MV;
20084 }
20085 }
20086 elsif($Type eq "short")
20087 { # libSDL
20088 # libwbxml2
20089 return $3;
20090 }
20091 elsif($Type eq "shortest")
20092 { # SDL
20093 # wbxml
20094 return shortest_name($3);
20095 }
20096 }
20097 return "";# error
20098}
20099
20100sub parse_libname_symbian($$)
20101{
20102 my ($Name, $Type) = @_;
20103 my $Ext = getLIB_EXT("symbian");
20104 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
20105 { # libpthread{00010001}.dso
20106 if($Type eq "name")
20107 { # libpthread{00010001}
20108 return $2;
20109 }
20110 elsif($Type eq "name+ext")
20111 { # libpthread{00010001}.dso
20112 return $1;
20113 }
20114 elsif($Type eq "version")
20115 { # 00010001
20116 my $V = $4;
20117 $V=~s/\{(.+)\}/$1/;
20118 return $V;
20119 }
20120 elsif($Type eq "short")
20121 { # libpthread
20122 return $3;
20123 }
20124 elsif($Type eq "shortest")
20125 { # pthread
20126 return shortest_name($3);
20127 }
20128 }
20129 return "";# error
20130}
20131
20132sub parse_libname_windows($$)
20133{
20134 my ($Name, $Type) = @_;
20135 my $Ext = getLIB_EXT("windows");
20136 if($Name=~/((.+?)\.$Ext)\Z/)
20137 { # netapi32.dll
20138 if($Type eq "name")
20139 { # netapi32
20140 return $2;
20141 }
20142 elsif($Type eq "name+ext")
20143 { # netapi32.dll
20144 return $1;
20145 }
20146 elsif($Type eq "version")
20147 { # DLL version embedded
20148 # at binary-level
20149 return "";
20150 }
20151 elsif($Type eq "short")
20152 { # netapi32
20153 return $2;
20154 }
20155 elsif($Type eq "shortest")
20156 { # netapi
20157 return shortest_name($2);
20158 }
20159 }
20160 return "";# error
20161}
20162
20163sub shortest_name($)
20164{
20165 my $Name = $_[0];
20166 # remove prefix
20167 $Name=~s/\A(lib|open)//;
20168 # remove suffix
20169 $Name=~s/[\W\d_]+\Z//i;
20170 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
20171 return $Name;
20172}
20173
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020174sub createSymbolsList($$$$$)
20175{
20176 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
20177 read_ABI_Dump(1, $DPath);
20178 if(not $CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020179 prepareSymbols(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020180 }
20181 my %SymbolHeaderLib = ();
20182 my $Total = 0;
20183 # Get List
20184 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
20185 {
20186 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020187 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020188 next;
20189 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020190 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020191 { # skip other symbols
20192 next;
20193 }
20194 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
20195 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020196 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020197 next;
20198 }
20199 my $DyLib = $Symbol_Library{1}{$Symbol};
20200 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020201 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020202 next;
20203 }
20204 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
20205 $Total+=1;
20206 }
20207 # Draw List
20208 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
20209 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
20210 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
20211 {
20212 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
20213 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020214 my %NS_Symbol = ();
20215 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020216 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020217 }
20218 foreach my $NameSpace (sort keys(%NS_Symbol))
20219 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020220 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020221 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
20222 foreach my $Symbol (@SortedInterfaces)
20223 {
20224 my $SubReport = "";
20225 my $Signature = get_Signature($Symbol, 1);
20226 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020227 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020228 }
20229 if($Symbol=~/\A(_Z|\?)/)
20230 {
20231 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020232 $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 +040020233 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020234 else {
20235 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
20236 }
20237 }
20238 else
20239 {
20240 if($Signature) {
20241 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
20242 }
20243 else {
20244 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
20245 }
20246 }
20247 $SYMBOLS_LIST .= $SubReport;
20248 }
20249 }
20250 $SYMBOLS_LIST .= "<br/>\n";
20251 }
20252 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020253 # clear info
20254 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
20255 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
20256 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
20257 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020258 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020259 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020260 my $CssStyles = readModule("Styles", "SymbolsList.css");
20261 my $JScripts = readModule("Scripts", "Sections.js");
20262 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020263 my $Title = "$LName: public symbols";
20264 my $Keywords = "$LName, API, symbols";
20265 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020266 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020267 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020268 <br/><br/><hr/>\n".getReportFooter($LName, 1)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020269 <div style='height:999px;'></div></body></html>";
20270 writeFile($SaveTo, $SYMBOLS_LIST);
20271}
20272
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020273sub add_target_libs($)
20274{
20275 foreach (@{$_[0]}) {
20276 $TargetLibs{$_} = 1;
20277 }
20278}
20279
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020280sub is_target_lib($)
20281{
20282 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020283 if(not $LName) {
20284 return 0;
20285 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020286 if($TargetLibraryName
20287 and $LName!~/\Q$TargetLibraryName\E/) {
20288 return 0;
20289 }
20290 if(keys(%TargetLibs)
20291 and not $TargetLibs{$LName}
20292 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
20293 return 0;
20294 }
20295 return 1;
20296}
20297
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020298sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020299{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020300 my ($H, $V) = @_;
20301 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020302 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020303 if($TargetHeaders{$V}{$H}) {
20304 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020305 }
20306 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020307 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020308}
20309
20310sub checkVersionNum($$)
20311{
20312 my ($LibVersion, $Path) = @_;
20313 if(my $VerNum = $TargetVersion{$LibVersion}) {
20314 return $VerNum;
20315 }
20316 my $UsedAltDescr = 0;
20317 foreach my $Part (split(/\s*,\s*/, $Path))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020318 { # try to get version string from file path
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020319 next if(isDump($Part)); # ABI dump
20320 next if($Part=~/\.(xml|desc)\Z/i); # XML descriptor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020321 my $VerNum = "";
20322 if(parse_libname($Part, "name", $OStarget))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020323 {
20324 $UsedAltDescr = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020325 $VerNum = parse_libname($Part, "version", $OStarget);
20326 if(not $VerNum) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040020327 $VerNum = readStrVer($Part);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020328 }
20329 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020330 elsif(is_header($Part, 2, $LibVersion) or -d $Part)
20331 {
20332 $UsedAltDescr = 1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040020333 $VerNum = readStrVer($Part);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020334 }
20335 if($VerNum ne "")
20336 {
20337 $TargetVersion{$LibVersion} = $VerNum;
20338 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020339 printMsg("WARNING", "setting version number to $VerNum (use -vnum option to change it)");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020340 }
20341 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020342 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 +040020343 }
20344 return $TargetVersion{$LibVersion};
20345 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020346 }
20347 if($UsedAltDescr)
20348 {
20349 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020350 exitStatus("Error", "version number is not set (use -vnum option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020351 }
20352 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020353 exitStatus("Error", ($LibVersion==1?"1st":"2nd")." version number is not set (use -v$LibVersion option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020354 }
20355 }
20356}
20357
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040020358sub readStrVer($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020359{
20360 my $Str = $_[0];
20361 return "" if(not $Str);
20362 $Str=~s/\Q$TargetLibraryName\E//g;
20363 if($Str=~/(\/|\\|\w|\A)[\-\_]*(\d+[\d\.\-]+\d+|\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020364 { # .../libssh-0.4.0/...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020365 return $2;
20366 }
20367 elsif(my $V = parse_libname($Str, "version", $OStarget)) {
20368 return $V;
20369 }
20370 return "";
20371}
20372
20373sub readLibs($)
20374{
20375 my $LibVersion = $_[0];
20376 if($OStarget eq "windows")
20377 { # dumpbin.exe will crash
20378 # without VS Environment
20379 check_win32_env();
20380 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020381 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020382 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020383 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020384}
20385
20386sub dump_sorting($)
20387{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040020388 my $Hash = $_[0];
20389 return [] if(not $Hash);
20390 my @Keys = keys(%{$Hash});
20391 return [] if($#Keys<0);
20392 if($Keys[0]=~/\A\d+\Z/)
20393 { # numbers
20394 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020395 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040020396 else
20397 { # strings
20398 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020399 }
20400}
20401
20402sub printMsg($$)
20403{
20404 my ($Type, $Msg) = @_;
20405 if($Type!~/\AINFO/) {
20406 $Msg = $Type.": ".$Msg;
20407 }
20408 if($Type!~/_C\Z/) {
20409 $Msg .= "\n";
20410 }
20411 if($Quiet)
20412 { # --quiet option
20413 appendFile($COMMON_LOG_PATH, $Msg);
20414 }
20415 else
20416 {
20417 if($Type eq "ERROR") {
20418 print STDERR $Msg;
20419 }
20420 else {
20421 print $Msg;
20422 }
20423 }
20424}
20425
20426sub exitStatus($$)
20427{
20428 my ($Code, $Msg) = @_;
20429 printMsg("ERROR", $Msg);
20430 exit($ERROR_CODE{$Code});
20431}
20432
20433sub exitReport()
20434{ # the tool has run without any errors
20435 printReport();
20436 if($COMPILE_ERRORS)
20437 { # errors in headers may add false positives/negatives
20438 exit($ERROR_CODE{"Compile_Error"});
20439 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020440 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
20441 { # --binary
20442 exit($ERROR_CODE{"Incompatible"});
20443 }
20444 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
20445 { # --source
20446 exit($ERROR_CODE{"Incompatible"});
20447 }
20448 elsif($RESULT{"Source"}{"Problems"}
20449 or $RESULT{"Binary"}{"Problems"})
20450 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020451 exit($ERROR_CODE{"Incompatible"});
20452 }
20453 else {
20454 exit($ERROR_CODE{"Compatible"});
20455 }
20456}
20457
20458sub readRules($)
20459{
20460 my $Kind = $_[0];
20461 if(not -f $RULES_PATH{$Kind}) {
20462 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
20463 }
20464 my $Content = readFile($RULES_PATH{$Kind});
20465 while(my $Rule = parseTag(\$Content, "rule"))
20466 {
20467 my $RId = parseTag(\$Rule, "id");
20468 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
20469 foreach my $Prop (@Properties) {
20470 if(my $Value = parseTag(\$Rule, lc($Prop)))
20471 {
20472 $Value=~s/\n[ ]*//;
20473 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
20474 }
20475 }
20476 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
20477 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
20478 }
20479 else {
20480 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
20481 }
20482 }
20483}
20484
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020485sub getReportPath($)
20486{
20487 my $Level = $_[0];
20488 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
20489 if($Level eq "Binary")
20490 {
20491 if($BinaryReportPath)
20492 { # --bin-report-path
20493 return $BinaryReportPath;
20494 }
20495 elsif($OutputReportPath)
20496 { # --report-path
20497 return $OutputReportPath;
20498 }
20499 else
20500 { # default
20501 return $Dir."/abi_compat_report.$ReportFormat";
20502 }
20503 }
20504 elsif($Level eq "Source")
20505 {
20506 if($SourceReportPath)
20507 { # --src-report-path
20508 return $SourceReportPath;
20509 }
20510 elsif($OutputReportPath)
20511 { # --report-path
20512 return $OutputReportPath;
20513 }
20514 else
20515 { # default
20516 return $Dir."/src_compat_report.$ReportFormat";
20517 }
20518 }
20519 else
20520 {
20521 if($OutputReportPath)
20522 { # --report-path
20523 return $OutputReportPath;
20524 }
20525 else
20526 { # default
20527 return $Dir."/compat_report.$ReportFormat";
20528 }
20529 }
20530}
20531
20532sub printStatMsg($)
20533{
20534 my $Level = $_[0];
20535 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
20536}
20537
20538sub listAffected($)
20539{
20540 my $Level = $_[0];
20541 my $List = "";
20542 foreach (keys(%{$TotalAffected{$Level}}))
20543 {
20544 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
20545 { # skip "Low"-severity problems
20546 next;
20547 }
20548 $List .= "$_\n";
20549 }
20550 my $Dir = get_dirname(getReportPath($Level));
20551 if($Level eq "Binary") {
20552 writeFile($Dir."/abi_affected.txt", $List);
20553 }
20554 elsif($Level eq "Source") {
20555 writeFile($Dir."/src_affected.txt", $List);
20556 }
20557}
20558
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020559sub printReport()
20560{
20561 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020562 createReport();
20563 if($JoinReport or $DoubleReport)
20564 {
20565 if($RESULT{"Binary"}{"Problems"}
20566 or $RESULT{"Source"}{"Problems"}) {
20567 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020568 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020569 else {
20570 printMsg("INFO", "result: COMPATIBLE");
20571 }
20572 printStatMsg("Binary");
20573 printStatMsg("Source");
20574 if($ListAffected)
20575 { # --list-affected
20576 listAffected("Binary");
20577 listAffected("Source");
20578 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020579 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020580 elsif($BinaryOnly)
20581 {
20582 if($RESULT{"Binary"}{"Problems"}) {
20583 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
20584 }
20585 else {
20586 printMsg("INFO", "result: COMPATIBLE");
20587 }
20588 printStatMsg("Binary");
20589 if($ListAffected)
20590 { # --list-affected
20591 listAffected("Binary");
20592 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020593 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020594 elsif($SourceOnly)
20595 {
20596 if($RESULT{"Source"}{"Problems"}) {
20597 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
20598 }
20599 else {
20600 printMsg("INFO", "result: COMPATIBLE");
20601 }
20602 printStatMsg("Source");
20603 if($ListAffected)
20604 { # --list-affected
20605 listAffected("Source");
20606 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020607 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020608 if($StdOut)
20609 {
20610 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040020611 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020612 printMsg("INFO", "compatibility report has been generated to stdout");
20613 }
20614 else
20615 { # default
20616 printMsg("INFO", "compatibility reports have been generated to stdout");
20617 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020618 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020619 else
20620 {
20621 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040020622 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020623 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
20624 }
20625 elsif($DoubleReport)
20626 { # default
20627 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
20628 }
20629 elsif($BinaryOnly)
20630 { # --binary
20631 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
20632 }
20633 elsif($SourceOnly)
20634 { # --source
20635 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
20636 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020637 }
20638}
20639
20640sub check_win32_env()
20641{
20642 if(not $ENV{"DevEnvDir"}
20643 or not $ENV{"LIB"}) {
20644 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
20645 }
20646}
20647
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020648sub diffSets($$)
20649{
20650 my ($S1, $S2) = @_;
20651 my @SK1 = keys(%{$S1});
20652 my @SK2 = keys(%{$S2});
20653 if($#SK1!=$#SK2) {
20654 return 1;
20655 }
20656 foreach my $K1 (@SK1)
20657 {
20658 if(not defined $S2->{$K1}) {
20659 return 1;
20660 }
20661 }
20662 return 0;
20663}
20664
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020665sub create_ABI_Dump()
20666{
20667 if(not -e $DumpAPI) {
20668 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
20669 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020670 my @DParts = split(/\s*,\s*/, $DumpAPI);
20671 foreach my $Part (@DParts)
20672 {
20673 if(not -e $Part) {
20674 exitStatus("Access_Error", "can't access \'$Part\'");
20675 }
20676 }
20677 checkVersionNum(1, $DumpAPI);
20678 foreach my $Part (@DParts)
20679 {
20680 if(isDump($Part)) {
20681 read_ABI_Dump(1, $Part);
20682 }
20683 else {
20684 readDescriptor(1, createDescriptor(1, $Part));
20685 }
20686 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020687
20688 if(not $Descriptor{1}{"Version"})
20689 { # set to default: X
20690 $Descriptor{1}{"Version"} = "X";
20691 }
20692
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020693 initLogging(1);
20694 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020695
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020696 my $DumpPath = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi";
20697 $DumpPath .= ".".$AR_EXT; # gzipped by default
20698 if($OutputDumpPath)
20699 { # user defined path
20700 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020701 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020702 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
20703
20704 if(not $Archive and not $StdOut)
20705 { # check archive utilities
20706 if($OSgroup eq "windows")
20707 { # using zip
20708 my $ZipCmd = get_CmdPath("zip");
20709 if(not $ZipCmd) {
20710 exitStatus("Not_Found", "can't find \"zip\"");
20711 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020712 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020713 else
20714 { # using tar and gzip
20715 my $TarCmd = get_CmdPath("tar");
20716 if(not $TarCmd) {
20717 exitStatus("Not_Found", "can't find \"tar\"");
20718 }
20719 my $GzipCmd = get_CmdPath("gzip");
20720 if(not $GzipCmd) {
20721 exitStatus("Not_Found", "can't find \"gzip\"");
20722 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020723 }
20724 }
20725
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020726 if(not $Descriptor{1}{"Dump"})
20727 {
20728 if(not $CheckHeadersOnly) {
20729 readLibs(1);
20730 }
20731 if($CheckHeadersOnly) {
20732 setLanguage(1, "C++");
20733 }
20734 if(not $CheckObjectsOnly) {
20735 searchForHeaders(1);
20736 }
20737 $WORD_SIZE{1} = detectWordSize();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020738 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020739 if(not $Descriptor{1}{"Dump"})
20740 {
20741 if($Descriptor{1}{"Headers"}) {
20742 readHeaders(1);
20743 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020744 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020745 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020746 if(not keys(%{$SymbolInfo{1}}))
20747 { # check if created dump is valid
20748 if(not $ExtendedCheck and not $CheckObjectsOnly)
20749 {
20750 if($CheckHeadersOnly) {
20751 exitStatus("Empty_Set", "the set of public symbols is empty");
20752 }
20753 else {
20754 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
20755 }
20756 }
20757 }
20758 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020759 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020760 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
20761 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020762 if($ExtraDump)
20763 { # add unmangled names to the ABI dump
20764 my @Names = ();
20765 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
20766 {
20767 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
20768 push(@Names, $MnglName);
20769 }
20770 }
20771 translateSymbols(@Names, 1);
20772 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
20773 {
20774 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
20775 {
20776 if(my $Unmangled = $tr_name{$MnglName})
20777 {
20778 if($MnglName ne $Unmangled) {
20779 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
20780 }
20781 }
20782 }
20783 }
20784 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020785
20786 my %GccConstants = (); # built-in GCC constants
20787 foreach my $Name (keys(%{$Constants{1}}))
20788 {
20789 if(not defined $Constants{1}{$Name}{"Header"})
20790 {
20791 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
20792 delete($Constants{1}{$Name});
20793 }
20794 }
20795
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020796 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020797 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020798 "TypeInfo" => $TypeInfo{1},
20799 "SymbolInfo" => $SymbolInfo{1},
20800 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020801 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020802 "SymbolVersion" => $SymVer{1},
20803 "LibraryVersion" => $Descriptor{1}{"Version"},
20804 "LibraryName" => $TargetLibraryName,
20805 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020806 "SkipTypes" => $SkipTypes{1},
20807 "SkipSymbols" => $SkipSymbols{1},
20808 "SkipNameSpaces" => $SkipNameSpaces{1},
20809 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020810 "Headers" => \%HeadersInfo,
20811 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020812 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020813 "NameSpaces" => $NestedNameSpaces{1},
20814 "Target" => $OStarget,
20815 "Arch" => getArch(1),
20816 "WordSize" => $WORD_SIZE{1},
20817 "GccVersion" => get_dumpversion($GCC_PATH),
20818 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
20819 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
20820 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020821 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020822 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020823 }
20824 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020825 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020826 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020827 if($ExtendedCheck)
20828 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020829 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020830 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020831 if($BinaryOnly)
20832 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020833 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020834 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020835 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020836 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020837 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020838 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
20839 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020840 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020841
20842 my $ABI_DUMP = "";
20843 if($UseXML)
20844 {
20845 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020846 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020847 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020848 else
20849 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020850 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020851 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020852 if($StdOut)
20853 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020854 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020855 printMsg("INFO", "ABI dump has been generated to stdout");
20856 return;
20857 }
20858 else
20859 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020860 my ($DDir, $DName) = separate_path($DumpPath);
20861 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020862 if(not $Archive) {
20863 $DPath = $DumpPath;
20864 }
20865
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020866 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020867
20868 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020869 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020870 close(DUMP);
20871
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020872 if(not -s $DPath) {
20873 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
20874 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040020875 if($Archive) {
20876 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020877 }
20878
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020879 if($OutputDumpPath) {
20880 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040020881 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020882 else {
20883 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
20884 }
20885 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 +040020886 }
20887}
20888
20889sub quickEmptyReports()
20890{ # Quick "empty" reports
20891 # 4 times faster than merging equal dumps
20892 # NOTE: the dump contains the "LibraryVersion" attribute
20893 # if you change the version, then your dump will be different
20894 # OVERCOME: use -v1 and v2 options for comparing dumps
20895 # and don't change version in the XML descriptor (and dumps)
20896 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
20897 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
20898 {
20899 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
20900 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
20901 if($FilePath1 and $FilePath2)
20902 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020903 my $Line = readLineNum($FilePath1, 0);
20904 if($Line=~/xml/)
20905 { # XML format
20906 # is not supported yet
20907 return;
20908 }
20909
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020910 local $/ = undef;
20911
20912 open(DUMP1, $FilePath1);
20913 my $Content1 = <DUMP1>;
20914 close(DUMP1);
20915
20916 open(DUMP2, $FilePath2);
20917 my $Content2 = <DUMP2>;
20918 close(DUMP2);
20919
20920 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020921 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020922 # clean memory
20923 undef $Content2;
20924
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020925 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020926 my $ABIdump = eval($Content1);
20927
20928 # clean memory
20929 undef $Content1;
20930
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020931 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020932 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 +040020933 }
20934 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020935 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020936 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
20937 }
20938 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020939 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020940 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
20941 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020942 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020943 read_Libs_DumpInfo($ABIdump, 1);
20944 read_Machine_DumpInfo($ABIdump, 1);
20945 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020946
20947 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
20948 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
20949
20950 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
20951 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
20952
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020953 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
20954 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
20955 exitReport();
20956 }
20957 }
20958 }
20959}
20960
20961sub initLogging($)
20962{
20963 my $LibVersion = $_[0];
20964 # create log directory
20965 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
20966 if($OutputLogPath{$LibVersion})
20967 { # user-defined by -log-path option
20968 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
20969 }
20970 if($LogMode ne "n") {
20971 mkpath($LOG_DIR);
20972 }
20973 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020974 if($Debug)
20975 { # debug directory
20976 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020977
20978 if(not $ExtraInfo)
20979 { # enable --extra-info
20980 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
20981 }
20982
20983 # enable --extra-dump
20984 $ExtraDump = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020985 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040020986 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020987}
20988
20989sub writeLog($$)
20990{
20991 my ($LibVersion, $Msg) = @_;
20992 if($LogMode ne "n") {
20993 appendFile($LOG_PATH{$LibVersion}, $Msg);
20994 }
20995}
20996
20997sub resetLogging($)
20998{
20999 my $LibVersion = $_[0];
21000 if($LogMode!~/a|n/)
21001 { # remove old log
21002 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021003 if($Debug) {
21004 rmtree($DEBUG_PATH{$LibVersion});
21005 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021006 }
21007}
21008
21009sub printErrorLog($)
21010{
21011 my $LibVersion = $_[0];
21012 if($LogMode ne "n") {
21013 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
21014 }
21015}
21016
21017sub isDump($)
21018{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021019 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz|\.zip|\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021020 return $1;
21021 }
21022 return 0;
21023}
21024
21025sub isDump_U($)
21026{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021027 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021028 return $1;
21029 }
21030 return 0;
21031}
21032
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021033sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021034{
21035 # read input XML descriptors or ABI dumps
21036 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021037 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021038 }
21039 my @DParts1 = split(/\s*,\s*/, $Descriptor{1}{"Path"});
21040 foreach my $Part (@DParts1)
21041 {
21042 if(not -e $Part) {
21043 exitStatus("Access_Error", "can't access \'$Part\'");
21044 }
21045 }
21046 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021047 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021048 }
21049 my @DParts2 = split(/\s*,\s*/, $Descriptor{2}{"Path"});
21050 foreach my $Part (@DParts2)
21051 {
21052 if(not -e $Part) {
21053 exitStatus("Access_Error", "can't access \'$Part\'");
21054 }
21055 }
21056 detect_default_paths("bin"); # to extract dumps
21057 if($#DParts1==0 and $#DParts2==0
21058 and isDump($Descriptor{1}{"Path"})
21059 and isDump($Descriptor{2}{"Path"}))
21060 { # optimization: equal ABI dumps
21061 quickEmptyReports();
21062 }
21063 checkVersionNum(1, $Descriptor{1}{"Path"});
21064 checkVersionNum(2, $Descriptor{2}{"Path"});
21065 printMsg("INFO", "preparation, please wait ...");
21066 foreach my $Part (@DParts1)
21067 {
21068 if(isDump($Part)) {
21069 read_ABI_Dump(1, $Part);
21070 }
21071 else {
21072 readDescriptor(1, createDescriptor(1, $Part));
21073 }
21074 }
21075 foreach my $Part (@DParts2)
21076 {
21077 if(isDump($Part)) {
21078 read_ABI_Dump(2, $Part);
21079 }
21080 else {
21081 readDescriptor(2, createDescriptor(2, $Part));
21082 }
21083 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021084
21085 if(not $Descriptor{1}{"Version"})
21086 { # set to default: X
21087 $Descriptor{1}{"Version"} = "X";
21088 }
21089
21090 if(not $Descriptor{2}{"Version"})
21091 { # set to default: Y
21092 $Descriptor{2}{"Version"} = "Y";
21093 }
21094
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021095 initLogging(1);
21096 initLogging(2);
21097 # check consistency
21098 if(not $Descriptor{1}{"Headers"}
21099 and not $Descriptor{1}{"Libs"}) {
21100 exitStatus("Error", "descriptor d1 does not contain both header files and libraries info");
21101 }
21102 if(not $Descriptor{2}{"Headers"}
21103 and not $Descriptor{2}{"Libs"}) {
21104 exitStatus("Error", "descriptor d2 does not contain both header files and libraries info");
21105 }
21106 if($Descriptor{1}{"Headers"} and not $Descriptor{1}{"Libs"}
21107 and not $Descriptor{2}{"Headers"} and $Descriptor{2}{"Libs"}) {
21108 exitStatus("Error", "can't compare headers with $SLIB_TYPE libraries");
21109 }
21110 elsif(not $Descriptor{1}{"Headers"} and $Descriptor{1}{"Libs"}
21111 and $Descriptor{2}{"Headers"} and not $Descriptor{2}{"Libs"}) {
21112 exitStatus("Error", "can't compare $SLIB_TYPE libraries with headers");
21113 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021114 if(not $Descriptor{1}{"Headers"})
21115 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021116 if($CheckHeadersOnly_Opt) {
21117 exitStatus("Error", "can't find header files info in descriptor d1");
21118 }
21119 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021120 if(not $Descriptor{2}{"Headers"})
21121 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021122 if($CheckHeadersOnly_Opt) {
21123 exitStatus("Error", "can't find header files info in descriptor d2");
21124 }
21125 }
21126 if(not $Descriptor{1}{"Headers"}
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021127 or not $Descriptor{2}{"Headers"})
21128 {
21129 if(not $CheckObjectsOnly_Opt)
21130 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021131 printMsg("WARNING", "comparing $SLIB_TYPE libraries only");
21132 $CheckObjectsOnly = 1;
21133 }
21134 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021135 if(not $Descriptor{1}{"Libs"})
21136 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021137 if($CheckObjectsOnly_Opt) {
21138 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d1");
21139 }
21140 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021141 if(not $Descriptor{2}{"Libs"})
21142 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021143 if($CheckObjectsOnly_Opt) {
21144 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d2");
21145 }
21146 }
21147 if(not $Descriptor{1}{"Libs"}
21148 or not $Descriptor{2}{"Libs"})
21149 { # comparing standalone header files
21150 # comparing ABI dumps created with --headers-only
21151 if(not $CheckHeadersOnly_Opt)
21152 {
21153 printMsg("WARNING", "checking headers only");
21154 $CheckHeadersOnly = 1;
21155 }
21156 }
21157 if($UseDumps)
21158 { # --use-dumps
21159 # parallel processing
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021160 my $DumpPath1 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi.$AR_EXT";
21161 my $DumpPath2 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{2}{"Version"}.".abi.$AR_EXT";
21162
21163 unlink($DumpPath1);
21164 unlink($DumpPath2);
21165
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021166 my $pid = fork();
21167 if($pid)
21168 { # dump on two CPU cores
21169 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
21170 if($RelativeDirectory{1}) {
21171 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
21172 }
21173 if($OutputLogPath{1}) {
21174 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
21175 }
21176 if($CrossGcc) {
21177 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
21178 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021179 if($Quiet)
21180 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021181 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021182 @PARAMS = (@PARAMS, "-logging-mode", "a");
21183 }
21184 elsif($LogMode and $LogMode ne "w")
21185 { # "w" is default
21186 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021187 }
21188 if($ExtendedCheck) {
21189 @PARAMS = (@PARAMS, "-extended");
21190 }
21191 if($UserLang) {
21192 @PARAMS = (@PARAMS, "-lang", $UserLang);
21193 }
21194 if($TargetVersion{1}) {
21195 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
21196 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021197 if($BinaryOnly) {
21198 @PARAMS = (@PARAMS, "-binary");
21199 }
21200 if($SourceOnly) {
21201 @PARAMS = (@PARAMS, "-source");
21202 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021203 if($SortDump) {
21204 @PARAMS = (@PARAMS, "-sort");
21205 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021206 if($DumpFormat and $DumpFormat ne "perl") {
21207 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
21208 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021209 if($CheckHeadersOnly) {
21210 @PARAMS = (@PARAMS, "-headers-only");
21211 }
21212 if($CheckObjectsOnly) {
21213 @PARAMS = (@PARAMS, "-objects-only");
21214 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021215 if($Debug)
21216 {
21217 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021218 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021219 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021220 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021221 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021222 exit(1);
21223 }
21224 }
21225 else
21226 { # child
21227 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
21228 if($RelativeDirectory{2}) {
21229 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
21230 }
21231 if($OutputLogPath{2}) {
21232 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
21233 }
21234 if($CrossGcc) {
21235 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
21236 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021237 if($Quiet)
21238 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021239 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021240 @PARAMS = (@PARAMS, "-logging-mode", "a");
21241 }
21242 elsif($LogMode and $LogMode ne "w")
21243 { # "w" is default
21244 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021245 }
21246 if($ExtendedCheck) {
21247 @PARAMS = (@PARAMS, "-extended");
21248 }
21249 if($UserLang) {
21250 @PARAMS = (@PARAMS, "-lang", $UserLang);
21251 }
21252 if($TargetVersion{2}) {
21253 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
21254 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021255 if($BinaryOnly) {
21256 @PARAMS = (@PARAMS, "-binary");
21257 }
21258 if($SourceOnly) {
21259 @PARAMS = (@PARAMS, "-source");
21260 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021261 if($SortDump) {
21262 @PARAMS = (@PARAMS, "-sort");
21263 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021264 if($DumpFormat and $DumpFormat ne "perl") {
21265 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
21266 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021267 if($CheckHeadersOnly) {
21268 @PARAMS = (@PARAMS, "-headers-only");
21269 }
21270 if($CheckObjectsOnly) {
21271 @PARAMS = (@PARAMS, "-objects-only");
21272 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021273 if($Debug)
21274 {
21275 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021276 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021277 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021278 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021279 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021280 exit(1);
21281 }
21282 else {
21283 exit(0);
21284 }
21285 }
21286 waitpid($pid, 0);
21287 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021288 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
21289 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021290 if($TargetLibraryFName ne $TargetLibraryName) {
21291 @CMP_PARAMS = (@CMP_PARAMS, "-l-full", $TargetLibraryFName);
21292 }
21293 if($ShowRetVal) {
21294 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
21295 }
21296 if($CrossGcc) {
21297 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
21298 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021299 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
21300 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021301 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021302 }
21303 if($ReportFormat and $ReportFormat ne "html")
21304 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021305 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
21306 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021307 if($OutputReportPath) {
21308 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
21309 }
21310 if($BinaryReportPath) {
21311 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
21312 }
21313 if($SourceReportPath) {
21314 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
21315 }
21316 if($LoggingPath) {
21317 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
21318 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021319 if($CheckHeadersOnly) {
21320 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
21321 }
21322 if($CheckObjectsOnly) {
21323 @CMP_PARAMS = (@CMP_PARAMS, "-objects-only");
21324 }
21325 if($BinaryOnly) {
21326 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
21327 }
21328 if($SourceOnly) {
21329 @CMP_PARAMS = (@CMP_PARAMS, "-source");
21330 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021331 if($Browse) {
21332 @CMP_PARAMS = (@CMP_PARAMS, "-browse", $Browse);
21333 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021334 if($OpenReport) {
21335 @CMP_PARAMS = (@CMP_PARAMS, "-open");
21336 }
21337 if($Debug)
21338 {
21339 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
21340 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021341 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021342 system("perl", $0, @CMP_PARAMS);
21343 exit($?>>8);
21344 }
21345 if(not $Descriptor{1}{"Dump"}
21346 or not $Descriptor{2}{"Dump"})
21347 { # need GCC toolchain to analyze
21348 # header files and libraries
21349 detect_default_paths("inc|lib|gcc");
21350 }
21351 if(not $Descriptor{1}{"Dump"})
21352 {
21353 if(not $CheckHeadersOnly) {
21354 readLibs(1);
21355 }
21356 if($CheckHeadersOnly) {
21357 setLanguage(1, "C++");
21358 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021359 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021360 searchForHeaders(1);
21361 }
21362 $WORD_SIZE{1} = detectWordSize();
21363 }
21364 if(not $Descriptor{2}{"Dump"})
21365 {
21366 if(not $CheckHeadersOnly) {
21367 readLibs(2);
21368 }
21369 if($CheckHeadersOnly) {
21370 setLanguage(2, "C++");
21371 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021372 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021373 searchForHeaders(2);
21374 }
21375 $WORD_SIZE{2} = detectWordSize();
21376 }
21377 if($WORD_SIZE{1} ne $WORD_SIZE{2})
21378 { # support for old ABI dumps
21379 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021380 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021381 {
21382 $WORD_SIZE{1} = $WORD_SIZE{2};
21383 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
21384 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021385 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021386 {
21387 $WORD_SIZE{2} = $WORD_SIZE{1};
21388 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
21389 }
21390 }
21391 elsif(not $WORD_SIZE{1}
21392 and not $WORD_SIZE{2})
21393 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021394 $WORD_SIZE{1} = "4";
21395 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021396 }
21397 if($Descriptor{1}{"Dump"})
21398 { # support for old ABI dumps
21399 prepareTypes(1);
21400 }
21401 if($Descriptor{2}{"Dump"})
21402 { # support for old ABI dumps
21403 prepareTypes(2);
21404 }
21405 if($AppPath and not keys(%{$Symbol_Library{1}})) {
21406 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
21407 }
21408 # started to process input data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021409 if(not $CheckObjectsOnly)
21410 {
21411 if($Descriptor{1}{"Headers"}
21412 and not $Descriptor{1}{"Dump"}) {
21413 readHeaders(1);
21414 }
21415 if($Descriptor{2}{"Headers"}
21416 and not $Descriptor{2}{"Dump"}) {
21417 readHeaders(2);
21418 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021419 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021420
21421 # clean memory
21422 %SystemHeaders = ();
21423 %mangled_name_gcc = ();
21424
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021425 prepareSymbols(1);
21426 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021427
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021428 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021429 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021430
21431 # Virtual Tables
21432 registerVTable(1);
21433 registerVTable(2);
21434
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021435 if(not checkDump(1, "1.22")
21436 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021437 { # support for old ABI dumps
21438 foreach my $ClassName (keys(%{$VirtualTable{2}}))
21439 {
21440 if($ClassName=~/</)
21441 { # templates
21442 if(not defined $VirtualTable{1}{$ClassName})
21443 { # synchronize
21444 delete($VirtualTable{2}{$ClassName});
21445 }
21446 }
21447 }
21448 }
21449
21450 registerOverriding(1);
21451 registerOverriding(2);
21452
21453 setVirtFuncPositions(1);
21454 setVirtFuncPositions(2);
21455
21456 # Other
21457 addParamNames(1);
21458 addParamNames(2);
21459
21460 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021461}
21462
21463sub compareAPIs($)
21464{
21465 my $Level = $_[0];
21466 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021467 loadModule("CallConv");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021468 if($Level eq "Binary") {
21469 printMsg("INFO", "comparing ABIs ...");
21470 }
21471 else {
21472 printMsg("INFO", "comparing APIs ...");
21473 }
21474 if($CheckHeadersOnly
21475 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021476 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021477 detectAdded_H($Level);
21478 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021479 }
21480 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021481 { # added/removed in libs
21482 detectAdded($Level);
21483 detectRemoved($Level);
21484 }
21485 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021486 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021487 mergeSymbols($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021488 if(keys(%{$CheckedSymbols{$Level}})) {
21489 mergeConstants($Level);
21490 }
21491 }
21492 if($CheckHeadersOnly
21493 or $Level eq "Source")
21494 { # added/removed in headers
21495 mergeHeaders($Level);
21496 }
21497 else
21498 { # added/removed in libs
21499 mergeLibs($Level);
21500 if($CheckImpl
21501 and $Level eq "Binary") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021502 mergeImpl();
21503 }
21504 }
21505}
21506
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021507sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021508{
21509 my %Opts = (
21510 "OStarget"=>$OStarget,
21511 "Debug"=>$Debug,
21512 "Quiet"=>$Quiet,
21513 "LogMode"=>$LogMode,
21514 "CheckHeadersOnly"=>$CheckHeadersOnly,
21515
21516 "SystemRoot"=>$SystemRoot,
21517 "MODULES_DIR"=>$MODULES_DIR,
21518 "GCC_PATH"=>$GCC_PATH,
21519 "TargetSysInfo"=>$TargetSysInfo,
21520 "CrossPrefix"=>$CrossPrefix,
21521 "TargetLibraryName"=>$TargetLibraryName,
21522 "CrossGcc"=>$CrossGcc,
21523 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021524 "NoStdInc"=>$NoStdInc,
21525
21526 "BinaryOnly" => $BinaryOnly,
21527 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021528 );
21529 return \%Opts;
21530}
21531
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021532sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021533{
21534 my %CODE_ERROR = reverse(%ERROR_CODE);
21535 return $CODE_ERROR{$_[0]};
21536}
21537
21538sub scenario()
21539{
21540 if($StdOut)
21541 { # enable quiet mode
21542 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021543 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021544 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021545 if(not $LogMode)
21546 { # default
21547 $LogMode = "w";
21548 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021549 if($UserLang)
21550 { # --lang=C++
21551 $UserLang = uc($UserLang);
21552 $COMMON_LANGUAGE{1}=$UserLang;
21553 $COMMON_LANGUAGE{2}=$UserLang;
21554 }
21555 if($LoggingPath)
21556 {
21557 $OutputLogPath{1} = $LoggingPath;
21558 $OutputLogPath{2} = $LoggingPath;
21559 if($Quiet) {
21560 $COMMON_LOG_PATH = $LoggingPath;
21561 }
21562 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021563 if($OutputDumpPath)
21564 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021565 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021566 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
21567 }
21568 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021569 if($BinaryOnly and $SourceOnly)
21570 { # both --binary and --source
21571 # is the default mode
21572 $DoubleReport = 1;
21573 $JoinReport = 0;
21574 $BinaryOnly = 0;
21575 $SourceOnly = 0;
21576 if($OutputReportPath)
21577 { # --report-path
21578 $DoubleReport = 0;
21579 $JoinReport = 1;
21580 }
21581 }
21582 elsif($BinaryOnly or $SourceOnly)
21583 { # --binary or --source
21584 $DoubleReport = 0;
21585 $JoinReport = 0;
21586 }
21587 if($UseXML)
21588 { # --xml option
21589 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021590 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021591 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021592 if($ReportFormat)
21593 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021594 $ReportFormat = lc($ReportFormat);
21595 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021596 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021597 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021598 if($ReportFormat eq "htm")
21599 { # HTM == HTML
21600 $ReportFormat = "html";
21601 }
21602 elsif($ReportFormat eq "xml")
21603 { # --report-format=XML equal to --xml
21604 $UseXML = 1;
21605 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021606 }
21607 else
21608 { # default: HTML
21609 $ReportFormat = "html";
21610 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021611 if($DumpFormat)
21612 { # validate
21613 $DumpFormat = lc($DumpFormat);
21614 if($DumpFormat!~/\A(xml|perl)\Z/) {
21615 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
21616 }
21617 if($DumpFormat eq "xml")
21618 { # --dump-format=XML equal to --xml
21619 $UseXML = 1;
21620 }
21621 }
21622 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021623 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021624 $DumpFormat = "perl";
21625 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021626 if($Quiet and $LogMode!~/a|n/)
21627 { # --quiet log
21628 if(-f $COMMON_LOG_PATH) {
21629 unlink($COMMON_LOG_PATH);
21630 }
21631 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021632 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021633 $CheckUndefined = 1;
21634 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021635 if($TestTool and $UseDumps)
21636 { # --test && --use-dumps == --test-dump
21637 $TestDump = 1;
21638 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021639 if($Tolerant)
21640 { # enable all
21641 $Tolerance = 1234;
21642 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021643 if($Help)
21644 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021645 HELP_MESSAGE();
21646 exit(0);
21647 }
21648 if($InfoMsg) {
21649 INFO_MESSAGE();
21650 exit(0);
21651 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021652 if($ShowVersion)
21653 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021654 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.");
21655 exit(0);
21656 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021657 if($DumpVersion)
21658 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021659 printMsg("INFO", $TOOL_VERSION);
21660 exit(0);
21661 }
21662 if($ExtendedCheck) {
21663 $CheckHeadersOnly = 1;
21664 }
21665 if($SystemRoot_Opt)
21666 { # user defined root
21667 if(not -e $SystemRoot_Opt) {
21668 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
21669 }
21670 $SystemRoot = $SystemRoot_Opt;
21671 $SystemRoot=~s/[\/]+\Z//g;
21672 if($SystemRoot) {
21673 $SystemRoot = get_abs_path($SystemRoot);
21674 }
21675 }
21676 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021677
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021678 if($SortDump)
21679 {
21680 $Data::Dumper::Useperl = 1;
21681 $Data::Dumper::Sortkeys = \&dump_sorting;
21682 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021683
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021684 if($TargetLibsPath)
21685 {
21686 if(not -f $TargetLibsPath) {
21687 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
21688 }
21689 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
21690 $TargetLibs{$Lib} = 1;
21691 }
21692 }
21693 if($TargetHeadersPath)
21694 { # --headers-list
21695 if(not -f $TargetHeadersPath) {
21696 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
21697 }
21698 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
21699 {
21700 $TargetHeaders{1}{$Header} = 1;
21701 $TargetHeaders{2}{$Header} = 1;
21702 }
21703 }
21704 if($TargetHeader)
21705 { # --header
21706 $TargetHeaders{1}{$TargetHeader} = 1;
21707 $TargetHeaders{2}{$TargetHeader} = 1;
21708 }
21709 if($TestTool
21710 or $TestDump)
21711 { # --test, --test-dump
21712 detect_default_paths("bin|gcc"); # to compile libs
21713 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021714 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
21715 $LIB_EXT, $GCC_PATH, $Browse, $OpenReport, $SortDump, $CheckHeadersOnly, $CheckObjectsOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021716 exit(0);
21717 }
21718 if($DumpSystem)
21719 { # --dump-system
21720 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021721 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021722 { # system XML descriptor
21723 if(not -f $DumpSystem) {
21724 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
21725 }
21726 my $Ret = readSystemDescriptor(readFile($DumpSystem));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021727 foreach (@{$Ret->{"Tools"}})
21728 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021729 push_U($SystemPaths{"bin"}, $_);
21730 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021731 }
21732 if($Ret->{"CrossPrefix"}) {
21733 $CrossPrefix = $Ret->{"CrossPrefix"};
21734 }
21735 }
21736 elsif($SystemRoot_Opt)
21737 { # -sysroot "/" option
21738 # default target: /usr/lib, /usr/include
21739 # search libs: /usr/lib and /lib
21740 if(not -e $SystemRoot."/usr/lib") {
21741 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
21742 }
21743 if(not -e $SystemRoot."/lib") {
21744 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
21745 }
21746 if(not -e $SystemRoot."/usr/include") {
21747 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
21748 }
21749 readSystemDescriptor("
21750 <name>
21751 $DumpSystem
21752 </name>
21753 <headers>
21754 $SystemRoot/usr/include
21755 </headers>
21756 <libs>
21757 $SystemRoot/usr/lib
21758 </libs>
21759 <search_libs>
21760 $SystemRoot/lib
21761 </search_libs>");
21762 }
21763 else {
21764 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
21765 }
21766 detect_default_paths("bin|gcc"); # to check symbols
21767 if($OStarget eq "windows")
21768 { # to run dumpbin.exe
21769 # and undname.exe
21770 check_win32_env();
21771 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021772 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021773 exit(0);
21774 }
21775 if($CmpSystems)
21776 { # --cmp-systems
21777 detect_default_paths("bin"); # to extract dumps
21778 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021779 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021780 exit(0);
21781 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021782 if($GenerateTemplate)
21783 {
21784 writeFile("VERSION.xml", $DescriptorTemplate."\n");
21785 printMsg("INFO", "XML-descriptor template ./VERSION.xml has been generated");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021786 exit(0);
21787 }
21788 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021789 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021790 }
21791 else
21792 { # validate library name
21793 if($TargetLibraryName=~/[\*\/\\]/) {
21794 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
21795 }
21796 }
21797 if(not $TargetLibraryFName) {
21798 $TargetLibraryFName = $TargetLibraryName;
21799 }
21800 if($CheckHeadersOnly_Opt and $CheckObjectsOnly_Opt) {
21801 exitStatus("Error", "you can't specify both -headers-only and -objects-only options at the same time");
21802 }
21803 if($SymbolsListPath)
21804 {
21805 if(not -f $SymbolsListPath) {
21806 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
21807 }
21808 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
21809 $SymbolsList{$Interface} = 1;
21810 }
21811 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021812 if($SkipSymbolsListPath)
21813 {
21814 if(not -f $SkipSymbolsListPath) {
21815 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
21816 }
21817 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath))) {
21818 $SkipSymbolsList{$Interface} = 1;
21819 }
21820 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021821 if($SkipHeadersPath)
21822 {
21823 if(not -f $SkipHeadersPath) {
21824 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
21825 }
21826 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021827 { # register for both versions
21828 $SkipHeadersList{1}{$Path} = 1;
21829 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021830 my ($CPath, $Type) = classifyPath($Path);
21831 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021832 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021833 }
21834 }
21835 if($ParamNamesPath)
21836 {
21837 if(not -f $ParamNamesPath) {
21838 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
21839 }
21840 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
21841 {
21842 if($Line=~s/\A(\w+)\;//)
21843 {
21844 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021845 if($Line=~/;(\d+);/)
21846 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021847 while($Line=~s/(\d+);(\w+)//) {
21848 $AddIntParams{$Interface}{$1}=$2;
21849 }
21850 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021851 else
21852 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021853 my $Num = 0;
21854 foreach my $Name (split(/;/, $Line)) {
21855 $AddIntParams{$Interface}{$Num++}=$Name;
21856 }
21857 }
21858 }
21859 }
21860 }
21861 if($AppPath)
21862 {
21863 if(not -f $AppPath) {
21864 exitStatus("Access_Error", "can't access file \'$AppPath\'");
21865 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021866 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021867 $SymbolsList_App{$Interface} = 1;
21868 }
21869 }
21870 if($DumpAPI)
21871 { # --dump-abi
21872 # make an API dump
21873 create_ABI_Dump();
21874 exit($COMPILE_ERRORS);
21875 }
21876 # default: compare APIs
21877 # -d1 <path>
21878 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021879 compareInit();
21880 if($JoinReport or $DoubleReport)
21881 {
21882 compareAPIs("Binary");
21883 compareAPIs("Source");
21884 }
21885 elsif($BinaryOnly) {
21886 compareAPIs("Binary");
21887 }
21888 elsif($SourceOnly) {
21889 compareAPIs("Source");
21890 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021891 exitReport();
21892}
21893
21894scenario();