blob: ea2f79317e0763ef446be693ce6970bffc661212 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04003# ABI Compliance Checker (ACC) 1.99.2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004# A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005#
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006# Copyright (C) 2009-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 Ponomarenko46bef512013-06-14 16:33:03 +040066my $TOOL_VERSION = "1.99.2";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040067my $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 Ponomarenko46bef512013-06-14 16:33:03 +04005190 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005191 }
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 Ponomarenko46bef512013-06-14 16:33:03 +04005214 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005215 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005216 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5217 {
5218 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5219 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5220 { # unnamed
5221 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($Pos+1);
5222 }
5223 }
5224 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5225 {
5226 if(getFuncType($InfoId) ne "Method" or $Pos>0)
5227 { # params
5228 if($OldId ne $ParamTypeId)
5229 {
5230 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5231 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5232
5233 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5234 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5235 }
5236 }
5237 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005238 }
5239 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005240 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005241 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005242 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5243 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005244 if($PurpType eq "nop_expr")
5245 { # func ( const char* arg = (const char*)(void*)0 )
5246 $PurpId = getTreeAttr_Op($PurpId);
5247 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005248 my $Val = getInitVal($PurpId, $ParamTypeId);
5249 if(defined $Val) {
5250 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5251 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005252 }
5253 }
5254 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005255 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005256 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005257 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005258}
5259
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005260sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005261{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005262 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5263 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005264 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5265 return $1;
5266 }
5267 }
5268 return "";
5269}
5270
5271sub getTreeAttr_Chain($)
5272{
5273 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5274 {
5275 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5276 return $1;
5277 }
5278 }
5279 return "";
5280}
5281
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005282sub getTreeAttr_Unql($)
5283{
5284 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5285 {
5286 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5287 return $1;
5288 }
5289 }
5290 return "";
5291}
5292
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005293sub getTreeAttr_Scpe($)
5294{
5295 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5296 {
5297 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5298 return $1;
5299 }
5300 }
5301 return "";
5302}
5303
5304sub getTreeAttr_Type($)
5305{
5306 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5307 {
5308 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5309 return $1;
5310 }
5311 }
5312 return "";
5313}
5314
5315sub getTreeAttr_Name($)
5316{
5317 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5318 {
5319 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5320 return $1;
5321 }
5322 }
5323 return "";
5324}
5325
5326sub getTreeAttr_Mngl($)
5327{
5328 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5329 {
5330 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5331 return $1;
5332 }
5333 }
5334 return "";
5335}
5336
5337sub getTreeAttr_Prms($)
5338{
5339 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5340 {
5341 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5342 return $1;
5343 }
5344 }
5345 return "";
5346}
5347
5348sub getTreeAttr_Fncs($)
5349{
5350 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5351 {
5352 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5353 return $1;
5354 }
5355 }
5356 return "";
5357}
5358
5359sub getTreeAttr_Csts($)
5360{
5361 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5362 {
5363 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5364 return $1;
5365 }
5366 }
5367 return "";
5368}
5369
5370sub getTreeAttr_Purp($)
5371{
5372 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5373 {
5374 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5375 return $1;
5376 }
5377 }
5378 return "";
5379}
5380
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005381sub getTreeAttr_Op($)
5382{
5383 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5384 {
5385 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5386 return $1;
5387 }
5388 }
5389 return "";
5390}
5391
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005392sub getTreeAttr_Valu($)
5393{
5394 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5395 {
5396 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5397 return $1;
5398 }
5399 }
5400 return "";
5401}
5402
5403sub getTreeAttr_Flds($)
5404{
5405 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5406 {
5407 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5408 return $1;
5409 }
5410 }
5411 return "";
5412}
5413
5414sub getTreeAttr_Args($)
5415{
5416 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5417 {
5418 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005419 return $1;
5420 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005421 }
5422 return "";
5423}
5424
5425sub getTreeValue($)
5426{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005427 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5428 {
5429 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5430 return $1;
5431 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005432 }
5433 return "";
5434}
5435
5436sub getTreeAccess($)
5437{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005438 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005439 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005440 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5441 {
5442 my $Access = $1;
5443 if($Access eq "prot") {
5444 return "protected";
5445 }
5446 elsif($Access eq "priv") {
5447 return "private";
5448 }
5449 }
5450 elsif($Info=~/ protected /)
5451 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005452 return "protected";
5453 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005454 elsif($Info=~/ private /)
5455 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005456 return "private";
5457 }
5458 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005459 return "public";
5460}
5461
5462sub setFuncAccess($)
5463{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005464 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005465 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005466 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005467 }
5468 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005469 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005470 }
5471}
5472
5473sub setTypeAccess($$)
5474{
5475 my ($TypeId, $TypeAttr) = @_;
5476 my $Access = getTreeAccess($TypeId);
5477 if($Access eq "protected") {
5478 $TypeAttr->{"Protected"} = 1;
5479 }
5480 elsif($Access eq "private") {
5481 $TypeAttr->{"Private"} = 1;
5482 }
5483}
5484
5485sub setFuncKind($)
5486{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005487 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5488 {
5489 if($Info=~/pseudo tmpl/) {
5490 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5491 }
5492 elsif($Info=~/ constructor /) {
5493 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5494 }
5495 elsif($Info=~/ destructor /) {
5496 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5497 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005498 }
5499}
5500
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005501sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005502{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005503 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5504 {
5505 if($Info=~/spec[ ]*:[ ]*pure /) {
5506 return "PureVirt";
5507 }
5508 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5509 return "Virt";
5510 }
5511 elsif($Info=~/ pure\s+virtual /)
5512 { # support for old GCC versions
5513 return "PureVirt";
5514 }
5515 elsif($Info=~/ virtual /)
5516 { # support for old GCC versions
5517 return "Virt";
5518 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005519 }
5520 return "";
5521}
5522
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005523sub getFuncLink($)
5524{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005525 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5526 {
5527 if($Info=~/link[ ]*:[ ]*static /) {
5528 return "Static";
5529 }
5530 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005531 return $1;
5532 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005533 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005534 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005535}
5536
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005537sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005538{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005539 my ($Symbol, $LibVersion) = @_;
5540 return "" if(not $Symbol or not $LibVersion);
5541 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
5542 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005543 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005544 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
5545 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
5546 }
5547 }
5548 if($NS)
5549 {
5550 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5551 return $NS;
5552 }
5553 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005554 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005555 while($NS=~s/::[^:]+\Z//)
5556 {
5557 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5558 return $NS;
5559 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005560 }
5561 }
5562 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005563
5564 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005565}
5566
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005567sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005568{
5569 my ($TypeName, $LibVersion) = @_;
5570 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005571 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005572 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005573 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5574 return $NS;
5575 }
5576 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005577 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005578 while($NS=~s/::[^:]+\Z//)
5579 {
5580 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
5581 return $NS;
5582 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005583 }
5584 }
5585 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005586 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005587}
5588
5589sub getNameSpace($)
5590{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005591 my $InfoId = $_[0];
5592 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005593 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005594 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005595 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005596 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005597 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005598 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
5599 {
5600 my $NameSpace = getTreeStr($1);
5601 if($NameSpace eq "::")
5602 { # global namespace
5603 return "";
5604 }
5605 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
5606 $NameSpace = $BaseNameSpace."::".$NameSpace;
5607 }
5608 $NestedNameSpaces{$Version}{$NameSpace} = 1;
5609 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005610 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005611 else {
5612 return "";
5613 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005614 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005615 elsif($InfoType eq "record_type")
5616 { # inside data type
5617 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
5618 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005619 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005620 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005621 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005622 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005623}
5624
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005625sub getEnumMembVal($)
5626{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005627 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005628 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005629 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
5630 {
5631 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
5632 {
5633 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
5634 { # in newer versions of GCC the value is in the "const_decl->cnst" node
5635 return getTreeValue($1);
5636 }
5637 else
5638 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
5639 return getTreeValue($1);
5640 }
5641 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005642 }
5643 }
5644 return "";
5645}
5646
5647sub getSize($)
5648{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005649 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5650 {
5651 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
5652 return getTreeValue($1);
5653 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005654 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005655 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005656}
5657
5658sub getAlgn($)
5659{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005660 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5661 {
5662 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
5663 return $1;
5664 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005665 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005666 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005667}
5668
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005669sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005670{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005671 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5672 {
5673 if($Info=~/ bitfield /) {
5674 return getSize($_[0]);
5675 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005676 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005677 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005678}
5679
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005680sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005681{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005682 if(my $Chan = getTreeAttr_Chan($_[0])) {
5683 return $Chan;
5684 }
5685 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
5686 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005687 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005688 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005689}
5690
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005691sub registerHeader($$)
5692{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005693 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005694 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005695 return "";
5696 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005697 if(is_abs($Header) and not -f $Header)
5698 { # incorrect absolute path
5699 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005700 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005701 if(skipHeader($Header, $LibVersion))
5702 { # skip
5703 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005704 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005705 if(my $Header_Path = identifyHeader($Header, $LibVersion))
5706 {
5707 detect_header_includes($Header_Path, $LibVersion);
5708
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005709 if(defined $Tolerance and $Tolerance=~/3/)
5710 { # 3 - skip headers that include non-Linux headers
5711 if($OSgroup ne "windows")
5712 {
5713 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
5714 {
5715 if(specificHeader($Inc, "windows")) {
5716 return "";
5717 }
5718 }
5719 }
5720 }
5721
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005722 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
5723 { # redirect
5724 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
5725 or skipHeader($RHeader_Path, $LibVersion))
5726 { # skip
5727 return "";
5728 }
5729 $Header_Path = $RHeader_Path;
5730 }
5731 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
5732 { # skip
5733 return "";
5734 }
5735
5736 if(my $HName = get_filename($Header_Path))
5737 { # register
5738 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
5739 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
5740 }
5741
5742 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
5743 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005744 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005745 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005746 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005747 }
5748
5749 if($CheckHeadersOnly
5750 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
5751 { # /usr/include/c++/4.6.1/...
5752 $STDCXX_TESTING = 1;
5753 }
5754
5755 return $Header_Path;
5756 }
5757 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005758}
5759
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005760sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005761{
5762 my ($Dir, $WithDeps, $LibVersion) = @_;
5763 $Dir=~s/[\/\\]+\Z//g;
5764 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005765 $Dir = get_abs_path($Dir);
5766 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005767 if($WithDeps)
5768 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005769 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
5770 return;
5771 }
5772 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
5773 $Mode = "DepsOnly";
5774 }
5775 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005776 else
5777 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005778 if($RegisteredDirs{$LibVersion}{$Dir}{1}
5779 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
5780 return;
5781 }
5782 }
5783 $Header_Dependency{$LibVersion}{$Dir} = 1;
5784 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
5785 if($Mode eq "DepsOnly")
5786 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005787 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005788 $Header_Dependency{$LibVersion}{$Path} = 1;
5789 }
5790 return;
5791 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005792 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005793 {
5794 if($WithDeps)
5795 {
5796 my $SubDir = $Path;
5797 while(($SubDir = get_dirname($SubDir)) ne $Dir)
5798 { # register all sub directories
5799 $Header_Dependency{$LibVersion}{$SubDir} = 1;
5800 }
5801 }
5802 next if(is_not_header($Path));
5803 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005804 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005805 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005806 $Include_Neighbors{$LibVersion}{$Part} = $Path;
5807 }
5808 }
5809 if(get_filename($Dir) eq "include")
5810 { # search for "lib/include/" directory
5811 my $LibDir = $Dir;
5812 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005813 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005814 }
5815 }
5816}
5817
5818sub parse_redirect($$$)
5819{
5820 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005821 my @Errors = ();
5822 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
5823 push(@Errors, $1);
5824 }
5825 my $Redirect = "";
5826 foreach (@Errors)
5827 {
5828 s/\s{2,}/ /g;
5829 if(/(only|must\ include
5830 |update\ to\ include
5831 |replaced\ with
5832 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005833 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005834 {
5835 $Redirect = $2;
5836 last;
5837 }
5838 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
5839 {
5840 $Redirect = $2;
5841 last;
5842 }
5843 elsif(/this\ header\ should\ not\ be\ used
5844 |programs\ should\ not\ directly\ include
5845 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
5846 |is\ not\ supported\ API\ for\ general\ use
5847 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005848 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005849 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
5850 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
5851 }
5852 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005853 if($Redirect)
5854 {
5855 $Redirect=~s/\A<//g;
5856 $Redirect=~s/>\Z//g;
5857 }
5858 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005859}
5860
5861sub parse_includes($$)
5862{
5863 my ($Content, $Path) = @_;
5864 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005865 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005866 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005867 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005868 my $Method = substr($Header, 0, 1, "");
5869 substr($Header, length($Header)-1, 1, "");
5870 $Header = path_format($Header, $OSgroup);
5871 if($Method eq "\"" or is_abs($Header))
5872 {
5873 if(-e join_P(get_dirname($Path), $Header))
5874 { # relative path exists
5875 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005876 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005877 else
5878 { # include "..." that doesn't exist is equal to include <...>
5879 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005880 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005881 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005882 else {
5883 $Includes{$Header} = 1;
5884 }
5885 }
5886 if($ExtraInfo)
5887 {
5888 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
5889 { # FT_FREETYPE_H
5890 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005891 }
5892 }
5893 return \%Includes;
5894}
5895
5896sub ignore_path($)
5897{
5898 my $Path = $_[0];
5899 if($Path=~/\~\Z/)
5900 {# skipping system backup files
5901 return 1;
5902 }
5903 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
5904 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
5905 return 1;
5906 }
5907 return 0;
5908}
5909
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005910sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005911{
5912 my ($ArrRef, $W) = @_;
5913 return if(length($W)<2);
5914 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
5915}
5916
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005917sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005918{
5919 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005920
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005921 $H1=~s/\.[a-z]+\Z//ig;
5922 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005923
5924 my $Hname1 = get_filename($H1);
5925 my $Hname2 = get_filename($H2);
5926 my $HDir1 = get_dirname($H1);
5927 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005928 my $Dirname1 = get_filename($HDir1);
5929 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005930
5931 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
5932 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
5933
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005934 if($_[0] eq $_[1]
5935 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005936 return 0;
5937 }
5938 elsif($H1=~/\A\Q$H2\E/) {
5939 return 1;
5940 }
5941 elsif($H2=~/\A\Q$H1\E/) {
5942 return -1;
5943 }
5944 elsif($HDir1=~/\Q$Hname1\E/i
5945 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005946 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005947 return -1;
5948 }
5949 elsif($HDir2=~/\Q$Hname2\E/i
5950 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005951 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005952 return 1;
5953 }
5954 elsif($Hname1=~/\Q$Dirname1\E/i
5955 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005956 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005957 return -1;
5958 }
5959 elsif($Hname2=~/\Q$Dirname2\E/i
5960 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005961 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005962 return 1;
5963 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005964 elsif($Hname1=~/(config|lib|util)/i
5965 and $Hname2!~/(config|lib|util)/i)
5966 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005967 return -1;
5968 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005969 elsif($Hname2=~/(config|lib|util)/i
5970 and $Hname1!~/(config|lib|util)/i)
5971 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005972 return 1;
5973 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005974 else
5975 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005976 my $R1 = checkRelevance($H1);
5977 my $R2 = checkRelevance($H2);
5978 if($R1 and not $R2)
5979 { # libebook/e-book.h
5980 return -1;
5981 }
5982 elsif($R2 and not $R1)
5983 { # libebook/e-book.h
5984 return 1;
5985 }
5986 else
5987 {
5988 return (lc($H1) cmp lc($H2));
5989 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005990 }
5991}
5992
5993sub searchForHeaders($)
5994{
5995 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005996
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005997 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005998 registerGccHeaders();
5999
6000 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6001 { # c++ standard include paths
6002 registerCppHeaders();
6003 }
6004
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006005 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006006 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6007 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006008 {
6009 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006010 if($SystemRoot)
6011 {
6012 if(is_abs($Path)) {
6013 $Path = $SystemRoot.$Path;
6014 }
6015 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006016 if(not -e $Path) {
6017 exitStatus("Access_Error", "can't access \'$Path\'");
6018 }
6019 elsif(-f $Path) {
6020 exitStatus("Access_Error", "\'$Path\' - not a directory");
6021 }
6022 elsif(-d $Path)
6023 {
6024 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006025 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006026 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6027 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006028 }
6029 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006030 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006031 }
6032 }
6033 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006034 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006035 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6036 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006037
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006038 # registering directories
6039 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6040 {
6041 next if(not -e $Path);
6042 $Path = get_abs_path($Path);
6043 $Path = path_format($Path, $OSgroup);
6044 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006045 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006046 }
6047 elsif(-f $Path)
6048 {
6049 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006050 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006051 and not $LocalIncludes{$Dir})
6052 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006053 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006054 # if(my $OutDir = get_dirname($Dir))
6055 # { # registering the outer directory
6056 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6057 # and not $LocalIncludes{$OutDir}) {
6058 # registerDir($OutDir, 0, $LibVersion);
6059 # }
6060 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006061 }
6062 }
6063 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006064
6065 # clean memory
6066 %RegisteredDirs = ();
6067
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006068 # registering headers
6069 my $Position = 0;
6070 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6071 {
6072 if(is_abs($Dest) and not -e $Dest) {
6073 exitStatus("Access_Error", "can't access \'$Dest\'");
6074 }
6075 $Dest = path_format($Dest, $OSgroup);
6076 if(is_header($Dest, 1, $LibVersion))
6077 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006078 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006079 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6080 }
6081 }
6082 elsif(-d $Dest)
6083 {
6084 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006085 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006086 {
6087 next if(ignore_path($Path));
6088 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006089 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006090 push(@Registered, $HPath);
6091 }
6092 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006093 @Registered = sort {sortHeaders($a, $b)} @Registered;
6094 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006095 foreach my $Path (@Registered) {
6096 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6097 }
6098 }
6099 else {
6100 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6101 }
6102 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006103
6104 if(defined $Tolerance and $Tolerance=~/4/)
6105 { # 4 - skip headers included by others
6106 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6107 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006108 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006109 delete($Registered_Headers{$LibVersion}{$Path});
6110 }
6111 }
6112 }
6113
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006114 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6115 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006116 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006117 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006118 if(is_abs($Header) and not -f $Header) {
6119 exitStatus("Access_Error", "can't access file \'$Header\'");
6120 }
6121 $Header = path_format($Header, $OSgroup);
6122 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6123 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006124 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006125 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006126 }
6127 else {
6128 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6129 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006130 }
6131 }
6132 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6133 { # set relative paths (for duplicates)
6134 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6135 { # search for duplicates
6136 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6137 my $Prefix = get_dirname($FirstPath);
6138 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6139 { # detect a shortest distinguishing prefix
6140 my $NewPrefix = $1;
6141 my %Identity = ();
6142 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6143 {
6144 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6145 $Identity{$Path} = $1;
6146 }
6147 }
6148 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6149 { # all names are differend with current prefix
6150 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6151 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6152 }
6153 last;
6154 }
6155 $Prefix = $NewPrefix; # increase prefix
6156 }
6157 }
6158 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006159
6160 # clean memory
6161 %HeaderName_Paths = ();
6162
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006163 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6164 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006165 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006166 my ($Pos, $PairPos) = (-1, -1);
6167 my ($Path, $PairPath) = ();
6168 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6169 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6170 foreach my $Header_Path (@Paths)
6171 {
6172 if(get_filename($Header_Path) eq $PairName)
6173 {
6174 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6175 $PairPath = $Header_Path;
6176 }
6177 if(get_filename($Header_Path) eq $HeaderName)
6178 {
6179 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6180 $Path = $Header_Path;
6181 }
6182 }
6183 if($PairPos!=-1 and $Pos!=-1
6184 and int($PairPos)<int($Pos))
6185 {
6186 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6187 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6188 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6189 }
6190 }
6191 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6192 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6193 }
6194}
6195
6196sub detect_real_includes($$)
6197{
6198 my ($AbsPath, $LibVersion) = @_;
6199 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6200 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6201 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6202 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6203 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006204 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6205
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006206 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6207 return () if(not $Path);
6208 open(PREPROC, $Path);
6209 while(<PREPROC>)
6210 {
6211 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6212 {
6213 my $Include = path_format($1, $OSgroup);
6214 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6215 next;
6216 }
6217 if($Include eq $AbsPath) {
6218 next;
6219 }
6220 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6221 }
6222 }
6223 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006224 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6225}
6226
6227sub detect_header_includes($$)
6228{
6229 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006230 return if(not $LibVersion or not $Path);
6231 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6232 return;
6233 }
6234 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6235
6236 if(not -e $Path) {
6237 return;
6238 }
6239
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006240 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006241 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6242 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006243 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006244 {
6245 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006246 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006247 }
6248 if($RedirectPath ne $Path) {
6249 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6250 }
6251 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006252 else
6253 { # can't find
6254 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6255 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006256 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006257 if(my $Inc = parse_includes($Content, $Path))
6258 {
6259 foreach my $Include (keys(%{$Inc}))
6260 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006261 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006262
6263 if(defined $Tolerance and $Tolerance=~/4/)
6264 {
6265 if(my $HPath = identifyHeader($Include, $LibVersion))
6266 {
6267 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6268 }
6269 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006270 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006271 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006272}
6273
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006274sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006275{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006276 my $Path = $_[0];
6277 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006278 if($OStarget eq "symbian")
6279 {
6280 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6281 { # epoc32/include/libc/{stdio, ...}.h
6282 return 1;
6283 }
6284 }
6285 else
6286 {
6287 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6288 { # /usr/include/{stdio, ...}.h
6289 return 1;
6290 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006291 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006292 return 0;
6293}
6294
6295sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006296{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006297 my $Dir = $_[0];
6298 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006299 if($OStarget eq "symbian")
6300 {
6301 if(get_filename($OutDir) eq "libc"
6302 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6303 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6304 return 1;
6305 }
6306 }
6307 else
6308 { # linux
6309 if($OutDir eq "/usr/include"
6310 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6311 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6312 return 1;
6313 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006314 }
6315 return 0;
6316}
6317
6318sub detect_recursive_includes($$)
6319{
6320 my ($AbsPath, $LibVersion) = @_;
6321 return () if(not $AbsPath);
6322 if(isCyclical(\@RecurInclude, $AbsPath)) {
6323 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6324 }
6325 my ($AbsDir, $Name) = separate_path($AbsPath);
6326 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006327 { # system GLIBC internals
6328 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006329 }
6330 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6331 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6332 }
6333 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006334
6335 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6336 { # skip /usr/include/c++/*/ headers
6337 return () if(not $ExtraInfo);
6338 }
6339
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006340 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006341 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006342 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006343 { # check "real" (non-"model") include paths
6344 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6345 pop(@RecurInclude);
6346 return @Paths;
6347 }
6348 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6349 detect_header_includes($AbsPath, $LibVersion);
6350 }
6351 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6352 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006353 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006354 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006355 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006356 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006357 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006358 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006359 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006360 }
6361 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006362 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006363 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006364 { # search for the nearest header
6365 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006366 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006367 if(-f $Candidate) {
6368 $HPath = $Candidate;
6369 }
6370 }
6371 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006372 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006373 }
6374 next if(not $HPath);
6375 if($HPath eq $AbsPath) {
6376 next;
6377 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006378
6379 if($Debug)
6380 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006381# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6382# {
6383# print STDERR "$AbsPath -> $HPath\n";
6384# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006385 }
6386
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006387 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6388 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006389 { # only include <...>, skip include "..." prefixes
6390 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6391 }
6392 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6393 {
6394 if($IncPath eq $AbsPath) {
6395 next;
6396 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006397 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6398 if($RIncType==-1)
6399 { # include "..."
6400 $RIncType = $IncType;
6401 }
6402 elsif($RIncType==2)
6403 {
6404 if($IncType!=-1) {
6405 $RIncType = $IncType;
6406 }
6407 }
6408 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006409 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6410 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6411 }
6412 }
6413 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6414 {
6415 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6416 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6417 { # distinguish math.h from glibc and math.h from the tested library
6418 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6419 last;
6420 }
6421 }
6422 }
6423 pop(@RecurInclude);
6424 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6425}
6426
6427sub find_in_framework($$$)
6428{
6429 my ($Header, $Framework, $LibVersion) = @_;
6430 return "" if(not $Header or not $Framework or not $LibVersion);
6431 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6432 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6433 }
6434 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6435 {
6436 if(get_filename($Dependency) eq $Framework
6437 and -f get_dirname($Dependency)."/".$Header) {
6438 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6439 }
6440 }
6441 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6442}
6443
6444sub find_in_defaults($)
6445{
6446 my $Header = $_[0];
6447 return "" if(not $Header);
6448 if(defined $Cache{"find_in_defaults"}{$Header}) {
6449 return $Cache{"find_in_defaults"}{$Header};
6450 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006451 foreach my $Dir (@DefaultIncPaths,
6452 @DefaultGccPaths,
6453 @DefaultCppPaths,
6454 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006455 {
6456 next if(not $Dir);
6457 if(-f $Dir."/".$Header) {
6458 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6459 }
6460 }
6461 return ($Cache{"find_in_defaults"}{$Header}="");
6462}
6463
6464sub cmp_paths($$)
6465{
6466 my ($Path1, $Path2) = @_;
6467 my @Parts1 = split(/[\/\\]/, $Path1);
6468 my @Parts2 = split(/[\/\\]/, $Path2);
6469 foreach my $Num (0 .. $#Parts1)
6470 {
6471 my $Part1 = $Parts1[$Num];
6472 my $Part2 = $Parts2[$Num];
6473 if($GlibcDir{$Part1}
6474 and not $GlibcDir{$Part2}) {
6475 return 1;
6476 }
6477 elsif($GlibcDir{$Part2}
6478 and not $GlibcDir{$Part1}) {
6479 return -1;
6480 }
6481 elsif($Part1=~/glib/
6482 and $Part2!~/glib/) {
6483 return 1;
6484 }
6485 elsif($Part1!~/glib/
6486 and $Part2=~/glib/) {
6487 return -1;
6488 }
6489 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6490 return $CmpRes;
6491 }
6492 }
6493 return 0;
6494}
6495
6496sub checkRelevance($)
6497{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006498 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006499 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006500
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006501 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006502 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006503 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006504
6505 my $Name = lc(get_filename($Path));
6506 my $Dir = lc(get_dirname($Path));
6507
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006508 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006509
6510 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006511 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006512 my $Len = length($Token);
6513 next if($Len<=1);
6514 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6515 { # include/evolution-data-server-1.4/libebook/e-book.h
6516 return 1;
6517 }
6518 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006519 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006520 return 1;
6521 }
6522 }
6523 return 0;
6524}
6525
6526sub checkFamily(@)
6527{
6528 my @Paths = @_;
6529 return 1 if($#Paths<=0);
6530 my %Prefix = ();
6531 foreach my $Path (@Paths)
6532 {
6533 if($SystemRoot) {
6534 $Path = cut_path_prefix($Path, $SystemRoot);
6535 }
6536 if(my $Dir = get_dirname($Path))
6537 {
6538 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6539 $Prefix{$Dir} += 1;
6540 $Prefix{get_dirname($Dir)} += 1;
6541 }
6542 }
6543 foreach (sort keys(%Prefix))
6544 {
6545 if(get_depth($_)>=3
6546 and $Prefix{$_}==$#Paths+1) {
6547 return 1;
6548 }
6549 }
6550 return 0;
6551}
6552
6553sub isAcceptable($$$)
6554{
6555 my ($Header, $Candidate, $LibVersion) = @_;
6556 my $HName = get_filename($Header);
6557 if(get_dirname($Header))
6558 { # with prefix
6559 return 1;
6560 }
6561 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
6562 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
6563 return 1;
6564 }
6565 if(checkRelevance($Candidate))
6566 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
6567 return 1;
6568 }
6569 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
6570 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
6571 # /usr/include/qt4/Qt/qsslconfiguration.h
6572 return 1;
6573 }
6574 if($OStarget eq "symbian")
6575 {
6576 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
6577 return 1;
6578 }
6579 }
6580 return 0;
6581}
6582
6583sub isRelevant($$$)
6584{ # disallow to search for "abstract" headers in too deep directories
6585 my ($Header, $Candidate, $LibVersion) = @_;
6586 my $HName = get_filename($Header);
6587 if($OStarget eq "symbian")
6588 {
6589 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
6590 return 0;
6591 }
6592 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006593 if($OStarget ne "bsd")
6594 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006595 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
6596 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
6597 return 0;
6598 }
6599 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006600 if($OStarget ne "windows")
6601 {
6602 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
6603 { # skip /usr/include/wine/msvcrt
6604 return 0;
6605 }
6606 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006607 if(not get_dirname($Header)
6608 and $Candidate=~/[\/\\]wx[\/\\]/)
6609 { # do NOT search in system /wx/ directory
6610 # for headers without a prefix: sstream.h
6611 return 0;
6612 }
6613 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
6614 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
6615 { # skip ../c++/3.3.3/ if using ../c++/4.5/
6616 return 0;
6617 }
6618 if($Candidate=~/[\/\\]asm-/
6619 and (my $Arch = getArch($LibVersion)) ne "unknown")
6620 { # arch-specific header files
6621 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
6622 {# skip ../asm-arm/ if using x86 architecture
6623 return 0;
6624 }
6625 }
6626 my @Candidates = getSystemHeaders($HName, $LibVersion);
6627 if($#Candidates==1)
6628 { # unique header
6629 return 1;
6630 }
6631 my @SCandidates = getSystemHeaders($Header, $LibVersion);
6632 if($#SCandidates==1)
6633 { # unique name
6634 return 1;
6635 }
6636 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
6637 if(get_depth($Candidate)-$SystemDepth>=5)
6638 { # abstract headers in too deep directories
6639 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
6640 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
6641 return 0;
6642 }
6643 }
6644 if($Header eq "parser.h"
6645 and $Candidate!~/\/libxml2\//)
6646 { # select parser.h from xml2 library
6647 return 0;
6648 }
6649 if(not get_dirname($Header)
6650 and keys(%{$SystemHeaders{$HName}})>=3)
6651 { # many headers with the same name
6652 # like thread.h included without a prefix
6653 if(not checkFamily(@Candidates)) {
6654 return 0;
6655 }
6656 }
6657 return 1;
6658}
6659
6660sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006661{ # cache function
6662 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
6663 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
6664 }
6665 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
6666}
6667
6668sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006669{
6670 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006671 if(-f $Header) {
6672 return $Header;
6673 }
6674 if(is_abs($Header) and not -f $Header)
6675 { # incorrect absolute path
6676 return "";
6677 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006678 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006679 { # too abstract configuration headers
6680 return "";
6681 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006682 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006683 if($OSgroup ne "windows")
6684 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006685 if(defined $WinHeaders{lc($HName)}
6686 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006687 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006688 return "";
6689 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006690 }
6691 if($OSgroup ne "macos")
6692 {
6693 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006694 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006695 return "";
6696 }
6697 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006698
6699 if(defined $ObsoleteHeaders{$HName})
6700 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006701 return "";
6702 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006703 if($OSgroup eq "linux" or $OSgroup eq "bsd")
6704 {
6705 if(defined $AlienHeaders{$HName}
6706 or defined $AlienHeaders{$Header})
6707 { # alien headers from other systems
6708 return "";
6709 }
6710 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006711
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006712 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006713 { # search in default paths
6714 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006715 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006716 }
6717 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006718 if(not keys(%SystemHeaders))
6719 { # register all headers in system include dirs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006720 detectSystemHeaders();
6721 }
6722 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
6723 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
6724 {
6725 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006726 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006727 }
6728 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006729 # error
6730 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006731}
6732
6733sub getSystemHeaders($$)
6734{
6735 my ($Header, $LibVersion) = @_;
6736 my @Candidates = ();
6737 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
6738 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006739 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006740 next;
6741 }
6742 push(@Candidates, $Candidate);
6743 }
6744 return @Candidates;
6745}
6746
6747sub cut_path_prefix($$)
6748{
6749 my ($Path, $Prefix) = @_;
6750 return $Path if(not $Prefix);
6751 $Prefix=~s/[\/\\]+\Z//;
6752 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
6753 return $Path;
6754}
6755
6756sub is_default_include_dir($)
6757{
6758 my $Dir = $_[0];
6759 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006760 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006761}
6762
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006763sub identifyHeader($$)
6764{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006765 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006766 if(not $Header) {
6767 return "";
6768 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006769 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006770 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
6771 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006772 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006773 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006774}
6775
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006776sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006777{ # search for header by absolute path, relative path or name
6778 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006779 if(-f $Header)
6780 { # it's relative or absolute path
6781 return get_abs_path($Header);
6782 }
6783 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
6784 and my $HeaderDir = find_in_defaults($Header))
6785 { # search for libc headers in the /usr/include
6786 # for non-libc target library before searching
6787 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006788 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006789 }
6790 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
6791 { # search in the target library paths
6792 return $Path;
6793 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006794 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006795 { # search in the internal GCC include paths
6796 return $DefaultGccHeader{$Header};
6797 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006798 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006799 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006800 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006801 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006802 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006803 { # search in the default G++ include paths
6804 return $DefaultCppHeader{$Header};
6805 }
6806 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
6807 { # search everywhere in the system
6808 return $AnyPath;
6809 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006810 elsif($OSgroup eq "macos")
6811 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
6812 if(my $Dir = get_dirname($Header))
6813 {
6814 my $RelPath = "Headers\/".get_filename($Header);
6815 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006816 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006817 }
6818 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006819 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006820 # cannot find anything
6821 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006822}
6823
6824sub getLocation($)
6825{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006826 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6827 {
6828 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006829 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006830 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006831 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006832 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006833}
6834
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006835sub getNameByInfo($)
6836{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006837 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006838 {
6839 if($Info=~/name[ ]*:[ ]*@(\d+) /)
6840 {
6841 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
6842 {
6843 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
6844 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006845 my $Str = $1;
6846 if($CppMode{$Version}
6847 and $Str=~/\Ac99_(.+)\Z/)
6848 {
6849 if($CppKeywords_A{$1}) {
6850 $Str=$1;
6851 }
6852 }
6853 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006854 }
6855 }
6856 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006857 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006858 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006859}
6860
6861sub getTreeStr($)
6862{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006863 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006864 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006865 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
6866 {
6867 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04006868 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006869 and $Str=~/\Ac99_(.+)\Z/)
6870 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006871 if($CppKeywords_A{$1}) {
6872 $Str=$1;
6873 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006874 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006875 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006876 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006877 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006878 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006879}
6880
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006881sub getFuncShortName($)
6882{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006883 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006884 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006885 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006886 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006887 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006888 {
6889 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
6890 {
6891 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
6892 return "operator ".$RName;
6893 }
6894 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006895 }
6896 else
6897 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006898 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
6899 {
6900 if(my $Ind = $Operator_Indication{$1}) {
6901 return "operator".$Ind;
6902 }
6903 elsif(not $UnknownOperator{$1})
6904 {
6905 printMsg("WARNING", "unknown operator $1");
6906 $UnknownOperator{$1} = 1;
6907 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006908 }
6909 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006910 }
6911 else
6912 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006913 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
6914 return getTreeStr($1);
6915 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006916 }
6917 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006918 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006919}
6920
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006921sub getFuncReturn($)
6922{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006923 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6924 {
6925 if($Info=~/type[ ]*:[ ]*@(\d+) /)
6926 {
6927 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
6928 return $1;
6929 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006930 }
6931 }
6932 return "";
6933}
6934
6935sub getFuncOrig($)
6936{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006937 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6938 {
6939 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
6940 return $1;
6941 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006942 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04006943 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006944}
6945
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006946sub unmangleArray(@)
6947{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006948 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006949 { # MSVC mangling
6950 my $UndNameCmd = get_CmdPath("undname");
6951 if(not $UndNameCmd) {
6952 exitStatus("Not_Found", "can't find \"undname\"");
6953 }
6954 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006955 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006956 }
6957 else
6958 { # GCC mangling
6959 my $CppFiltCmd = get_CmdPath("c++filt");
6960 if(not $CppFiltCmd) {
6961 exitStatus("Not_Found", "can't find c++filt in PATH");
6962 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006963 if(not defined $CPPFILT_SUPPORT_FILE)
6964 {
6965 my $Info = `$CppFiltCmd -h 2>&1`;
6966 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
6967 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006968 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006969 if($CPPFILT_SUPPORT_FILE)
6970 { # new versions of c++filt can take a file
6971 if($#_>$MAX_CPPFILT_FILE_SIZE)
6972 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
6973 # this is fixed in the oncoming version of Binutils
6974 my @Half = splice(@_, 0, ($#_+1)/2);
6975 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006976 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006977 else
6978 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006979 writeFile("$TMP_DIR/unmangle", join("\n", @_));
6980 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
6981 if($?==139)
6982 { # segmentation fault
6983 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
6984 }
6985 return split(/\n/, $Res);
6986 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006987 }
6988 else
6989 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006990 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
6991 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006992 my @Half = splice(@_, 0, ($#_+1)/2);
6993 return (unmangleArray(@Half), unmangleArray(@_))
6994 }
6995 else
6996 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006997 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006998 my $Res = `$CppFiltCmd $NoStrip $Strings`;
6999 if($?==139)
7000 { # segmentation fault
7001 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7002 }
7003 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007004 }
7005 }
7006 }
7007}
7008
7009sub get_SignatureNoInfo($$)
7010{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007011 my ($Symbol, $LibVersion) = @_;
7012 if($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol}) {
7013 return $Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007014 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007015 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007016 my $Signature = $tr_name{$MnglName}?$tr_name{$MnglName}:$MnglName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007017 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007018 { # C++
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04007019 # some standard typedefs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007020 $Signature=~s/\Qstd::basic_string<char, std::char_traits<char>, std::allocator<char> >\E/std::string/g;
7021 $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;
7022 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007023 if(not $CheckObjectsOnly or $OSgroup=~/linux|bsd|beos/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007024 { # ELF format marks data as OBJECT
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007025 if($GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007026 $Signature .= " [data]";
7027 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007028 elsif($Symbol!~/\A(_Z|\?)/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007029 $Signature .= " (...)";
7030 }
7031 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007032 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007033 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04007034 my $ShortName = substr($Signature, 0, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007035 $Signature=~s/\A\Q$ShortName\E/$ShortName $ChargeLevel/g;
7036 }
7037 if($SymbolVersion) {
7038 $Signature .= $VersionSpec.$SymbolVersion;
7039 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007040 return ($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007041}
7042
7043sub get_ChargeLevel($$)
7044{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007045 my ($Symbol, $LibVersion) = @_;
7046 return "" if($Symbol!~/\A(_Z|\?)/);
7047 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7048 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007049 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007050 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007051 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007052 if($Symbol=~/C1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007053 return "[in-charge]";
7054 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007055 elsif($Symbol=~/C2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007056 return "[not-in-charge]";
7057 }
7058 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007059 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007060 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007061 if($Symbol=~/D1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007062 return "[in-charge]";
7063 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007064 elsif($Symbol=~/D2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007065 return "[not-in-charge]";
7066 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007067 elsif($Symbol=~/D0E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007068 return "[in-charge-deleting]";
7069 }
7070 }
7071 }
7072 else
7073 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007074 if($Symbol=~/C1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007075 return "[in-charge]";
7076 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007077 elsif($Symbol=~/C2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007078 return "[not-in-charge]";
7079 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007080 elsif($Symbol=~/D1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007081 return "[in-charge]";
7082 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007083 elsif($Symbol=~/D2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007084 return "[not-in-charge]";
7085 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007086 elsif($Symbol=~/D0E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007087 return "[in-charge-deleting]";
7088 }
7089 }
7090 return "";
7091}
7092
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007093sub get_Signature_M($$)
7094{
7095 my ($Symbol, $LibVersion) = @_;
7096 my $Signature_M = $tr_name{$Symbol};
7097 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7098 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007099 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007100 }
7101 return $Signature_M;
7102}
7103
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007104sub get_Signature($$)
7105{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007106 my ($Symbol, $LibVersion) = @_;
7107 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7108 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007109 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007110 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
7111 if(isPrivateData($MnglName) or not $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007112 { # non-public global data
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007113 return get_SignatureNoInfo($Symbol, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007114 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007115 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007116 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7117 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007118 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007119 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7120 {
7121 $Signature .= $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::";
7122 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7123 $Signature .= "~";
7124 }
7125 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007126 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007127 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007128 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007129 }
7130 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007131 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007132 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007133 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7134 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007135 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007136 else
7137 {
7138 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007139 }
7140 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007141 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007142 {
7143 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007144 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007145 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007146 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007147 if(not $ParamTypeName) {
7148 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7149 }
7150 foreach my $Typedef (keys(%ChangedTypedef))
7151 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007152 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7153 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7154 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007155 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007156 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007157 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
7158 }
7159 else {
7160 push(@ParamArray, $ParamTypeName);
7161 }
7162 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007163 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7164 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007165 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007166 }
7167 else
7168 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007169 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007170 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007171 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007172 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007173 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007174 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7175 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007176 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007177 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007178 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7179 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007180 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007181 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007182 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7183 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007184 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007185 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007186 }
7187 }
7188 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007189 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007190 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007191 }
7192 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007193 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007194 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007195 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007196}
7197
7198sub create_member_decl($$)
7199{
7200 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007201 if($TName=~/\([\*]+\)/)
7202 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007203 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7204 return $TName;
7205 }
7206 else
7207 {
7208 my @ArraySizes = ();
7209 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7210 push(@ArraySizes, $1);
7211 }
7212 return $TName." ".$Member.join("", @ArraySizes);
7213 }
7214}
7215
7216sub getFuncType($)
7217{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007218 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7219 {
7220 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7221 {
7222 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7223 {
7224 if($Type eq "method_type") {
7225 return "Method";
7226 }
7227 elsif($Type eq "function_type") {
7228 return "Function";
7229 }
7230 else {
7231 return "Other";
7232 }
7233 }
7234 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007235 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007236 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007237}
7238
7239sub getFuncTypeId($)
7240{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007241 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7242 {
7243 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7244 return $1;
7245 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007246 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007247 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007248}
7249
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007250sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007251{ # "._N" or "$_N" in older GCC versions
7252 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007253}
7254
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007255sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007256{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007257 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7258 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007259 }
7260
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007261 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007262
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007263 if($_[1] ne "S")
7264 {
7265 $N=~s/\A[ ]+//g;
7266 $N=~s/[ ]+\Z//g;
7267 $N=~s/[ ]{2,}/ /g;
7268 }
7269
7270 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007271
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007272 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007273
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007274 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7275 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007276
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007277 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007278
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007279 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007280
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007281 if($_[1] eq "S")
7282 {
7283 if(index($N, "operator")!=-1) {
7284 $N=~s/\b(operator[ ]*)> >/$1>>/;
7285 }
7286 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007287
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007288 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007289}
7290
7291sub get_HeaderDeps($$)
7292{
7293 my ($AbsPath, $LibVersion) = @_;
7294 return () if(not $AbsPath or not $LibVersion);
7295 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7296 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7297 }
7298 my %IncDir = ();
7299 detect_recursive_includes($AbsPath, $LibVersion);
7300 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7301 {
7302 next if(not $HeaderPath);
7303 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7304 my $Dir = get_dirname($HeaderPath);
7305 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7306 {
7307 my $Dep = $Dir;
7308 if($Prefix)
7309 {
7310 if($OSgroup eq "windows")
7311 { # case insensitive seach on windows
7312 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7313 next;
7314 }
7315 }
7316 elsif($OSgroup eq "macos")
7317 { # seach in frameworks
7318 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7319 {
7320 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7321 {# frameworks
7322 my ($HFramework, $HName) = ($1, $2);
7323 $Dep = $HFramework;
7324 }
7325 else
7326 {# mismatch
7327 next;
7328 }
7329 }
7330 }
7331 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7332 { # Linux, FreeBSD
7333 next;
7334 }
7335 }
7336 if(not $Dep)
7337 { # nothing to include
7338 next;
7339 }
7340 if(is_default_include_dir($Dep))
7341 { # included by the compiler
7342 next;
7343 }
7344 if(get_depth($Dep)==1)
7345 { # too short
7346 next;
7347 }
7348 if(isLibcDir($Dep))
7349 { # do NOT include /usr/include/{sys,bits}
7350 next;
7351 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007352 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007353 }
7354 }
7355 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7356 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7357}
7358
7359sub sortIncPaths($$)
7360{
7361 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007362 if(not $ArrRef or $#{$ArrRef}<0) {
7363 return $ArrRef;
7364 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007365 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7366 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007367 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007368 return $ArrRef;
7369}
7370
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007371sub sortDeps($$$)
7372{
7373 if($Header_Dependency{$_[2]}{$_[0]}
7374 and not $Header_Dependency{$_[2]}{$_[1]}) {
7375 return 1;
7376 }
7377 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7378 and $Header_Dependency{$_[2]}{$_[1]}) {
7379 return -1;
7380 }
7381 return 0;
7382}
7383
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007384sub join_P($$)
7385{
7386 my $S = "/";
7387 if($OSgroup eq "windows") {
7388 $S = "\\";
7389 }
7390 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007391}
7392
7393sub get_namespace_additions($)
7394{
7395 my $NameSpaces = $_[0];
7396 my ($Additions, $AddNameSpaceId) = ("", 1);
7397 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7398 {
7399 next if($SkipNameSpaces{$Version}{$NS});
7400 next if(not $NS or $NameSpaces->{$NS}==-1);
7401 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7402 next if($NS=~/\A__/i);
7403 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007404 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007405 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7406 my @NS_Parts = split(/::/, $NS);
7407 next if($#NS_Parts==-1);
7408 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7409 foreach my $NS_Part (@NS_Parts)
7410 {
7411 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7412 $TypeDecl_Suffix .= "}";
7413 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007414 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007415 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7416 $Additions.=" $TypeDecl\n $FuncDecl\n";
7417 $AddNameSpaceId+=1;
7418 }
7419 return $Additions;
7420}
7421
7422sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007423{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007424 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007425 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007426 if($Fmt eq "windows")
7427 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007428 $Path=~s/\//\\/g;
7429 $Path=lc($Path);
7430 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007431 else
7432 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007433 $Path=~s/\\/\//g;
7434 }
7435 return $Path;
7436}
7437
7438sub inc_opt($$)
7439{
7440 my ($Path, $Style) = @_;
7441 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007442 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007443 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007444 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007445 return "-I\"".path_format($Path, "unix")."\"";
7446 }
7447 elsif($OSgroup eq "macos"
7448 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007449 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007450 return "-F".esc(get_dirname($Path));
7451 }
7452 else {
7453 return "-I".esc($Path);
7454 }
7455 }
7456 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007457 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007458 }
7459 return "";
7460}
7461
7462sub platformSpecs($)
7463{
7464 my $LibVersion = $_[0];
7465 my $Arch = getArch($LibVersion);
7466 if($OStarget eq "symbian")
7467 { # options for GCCE compiler
7468 my %Symbian_Opts = map {$_=>1} (
7469 "-D__GCCE__",
7470 "-DUNICODE",
7471 "-fexceptions",
7472 "-D__SYMBIAN32__",
7473 "-D__MARM_INTERWORK__",
7474 "-D_UNICODE",
7475 "-D__S60_50__",
7476 "-D__S60_3X__",
7477 "-D__SERIES60_3X__",
7478 "-D__EPOC32__",
7479 "-D__MARM__",
7480 "-D__EABI__",
7481 "-D__MARM_ARMV5__",
7482 "-D__SUPPORT_CPP_EXCEPTIONS__",
7483 "-march=armv5t",
7484 "-mapcs",
7485 "-mthumb-interwork",
7486 "-DEKA2",
7487 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7488 );
7489 return join(" ", keys(%Symbian_Opts));
7490 }
7491 elsif($OSgroup eq "windows"
7492 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7493 { # add options to MinGW compiler
7494 # to simulate the MSVC compiler
7495 my %MinGW_Opts = map {$_=>1} (
7496 "-D_WIN32",
7497 "-D_STDCALL_SUPPORTED",
7498 "-D__int64=\"long long\"",
7499 "-D__int32=int",
7500 "-D__int16=short",
7501 "-D__int8=char",
7502 "-D__possibly_notnullterminated=\" \"",
7503 "-D__nullterminated=\" \"",
7504 "-D__nullnullterminated=\" \"",
7505 "-D__w64=\" \"",
7506 "-D__ptr32=\" \"",
7507 "-D__ptr64=\" \"",
7508 "-D__forceinline=inline",
7509 "-D__inline=inline",
7510 "-D__uuidof(x)=IID()",
7511 "-D__try=",
7512 "-D__except(x)=",
7513 "-D__declspec(x)=__attribute__((x))",
7514 "-D__pragma(x)=",
7515 "-D_inline=inline",
7516 "-D__forceinline=__inline",
7517 "-D__stdcall=__attribute__((__stdcall__))",
7518 "-D__cdecl=__attribute__((__cdecl__))",
7519 "-D__fastcall=__attribute__((__fastcall__))",
7520 "-D__thiscall=__attribute__((__thiscall__))",
7521 "-D_stdcall=__attribute__((__stdcall__))",
7522 "-D_cdecl=__attribute__((__cdecl__))",
7523 "-D_fastcall=__attribute__((__fastcall__))",
7524 "-D_thiscall=__attribute__((__thiscall__))",
7525 "-DSHSTDAPI_(x)=x",
7526 "-D_MSC_EXTENSIONS",
7527 "-DSECURITY_WIN32",
7528 "-D_MSC_VER=1500",
7529 "-D_USE_DECLSPECS_FOR_SAL",
7530 "-D__noop=\" \"",
7531 "-DDECLSPEC_DEPRECATED=\" \"",
7532 "-D__builtin_alignof(x)=__alignof__(x)",
7533 "-DSORTPP_PASS");
7534 if($Arch eq "x86") {
7535 $MinGW_Opts{"-D_M_IX86=300"}=1;
7536 }
7537 elsif($Arch eq "x86_64") {
7538 $MinGW_Opts{"-D_M_AMD64=300"}=1;
7539 }
7540 elsif($Arch eq "ia64") {
7541 $MinGW_Opts{"-D_M_IA64=300"}=1;
7542 }
7543 return join(" ", keys(%MinGW_Opts));
7544 }
7545 return "";
7546}
7547
7548my %C_Structure = map {$_=>1} (
7549# FIXME: Can't separate union and struct data types before dumping,
7550# so it sometimes cause compilation errors for unknown reason
7551# when trying to declare TYPE* tmp_add_class_N
7552# This is a list of such structures + list of other C structures
7553 "sigval",
7554 "sigevent",
7555 "sigaction",
7556 "sigvec",
7557 "sigstack",
7558 "timeval",
7559 "timezone",
7560 "rusage",
7561 "rlimit",
7562 "wait",
7563 "flock",
7564 "stat",
7565 "_stat",
7566 "stat32",
7567 "_stat32",
7568 "stat64",
7569 "_stat64",
7570 "_stati64",
7571 "if_nameindex",
7572 "usb_device",
7573 "sigaltstack",
7574 "sysinfo",
7575 "timeLocale",
7576 "tcp_debug",
7577 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007578 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007579 "timespec",
7580 "random_data",
7581 "drand48_data",
7582 "_IO_marker",
7583 "_IO_FILE",
7584 "lconv",
7585 "sched_param",
7586 "tm",
7587 "itimerspec",
7588 "_pthread_cleanup_buffer",
7589 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007590 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007591 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007592 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007593 "sigcontext",
7594 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007595 # Mac
7596 "_timex",
7597 "_class_t",
7598 "_category_t",
7599 "_class_ro_t",
7600 "_protocol_t",
7601 "_message_ref_t",
7602 "_super_message_ref_t",
7603 "_ivar_t",
7604 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007605);
7606
7607sub getCompileCmd($$$)
7608{
7609 my ($Path, $Opt, $Inc) = @_;
7610 my $GccCall = $GCC_PATH;
7611 if($Opt) {
7612 $GccCall .= " ".$Opt;
7613 }
7614 $GccCall .= " -x ";
7615 if($OSgroup eq "macos") {
7616 $GccCall .= "objective-";
7617 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007618 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007619 { # compile as "C++" header
7620 # to obtain complete dump using GCC 4.0
7621 $GccCall .= "c++-header";
7622 }
7623 else
7624 { # compile as "C++" source
7625 # GCC 3.3 cannot compile headers
7626 $GccCall .= "c++";
7627 }
7628 if(my $Opts = platformSpecs($Version))
7629 {# platform-specific options
7630 $GccCall .= " ".$Opts;
7631 }
7632 # allow extra qualifications
7633 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007634 $GccCall .= " -fpermissive";
7635 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007636 if($NoStdInc)
7637 {
7638 $GccCall .= " -nostdinc";
7639 $GccCall .= " -nostdinc++";
7640 }
7641 if($CompilerOptions{$Version})
7642 { # user-defined options
7643 $GccCall .= " ".$CompilerOptions{$Version};
7644 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007645 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007646 if($Inc)
7647 { # include paths
7648 $GccCall .= " ".$Inc;
7649 }
7650 return $GccCall;
7651}
7652
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007653sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007654{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007655 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007656 my %HeaderElems = (
7657 # Types
7658 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007659 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007660 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
7661 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007662 "time.h" => ["time_t"],
7663 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007664 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
7665 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007666 "stdbool.h" => ["_Bool"],
7667 "rpc/xdr.h" => ["bool_t"],
7668 "in_systm.h" => ["n_long", "n_short"],
7669 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04007670 "arpa/inet.h" => ["fw_src", "ip_src"],
7671 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007672 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007673 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007674 );
7675 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007676 foreach (keys(%HeaderElems))
7677 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007678 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007679 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007680 }
7681 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007682 my %Types = ();
7683 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
7684 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007685 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007686 }
7687 if(keys(%Types))
7688 {
7689 my %AddHeaders = ();
7690 foreach my $Type (keys(%Types))
7691 {
7692 if(my $Header = $AutoPreamble{$Type})
7693 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007694 if(my $Path = identifyHeader($Header, $LibVersion))
7695 {
7696 if(skipHeader($Path, $LibVersion)) {
7697 next;
7698 }
7699 $Path = path_format($Path, $OSgroup);
7700 $AddHeaders{$Path}{"Type"} = $Type;
7701 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007702 }
7703 }
7704 }
7705 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007706 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007707 }
7708 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007709 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007710}
7711
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007712sub checkCTags($)
7713{
7714 my $Path = $_[0];
7715 if(not $Path) {
7716 return;
7717 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007718 my $CTags = undef;
7719
7720 if($OSgroup eq "bsd")
7721 { # use ectags on BSD
7722 $CTags = get_CmdPath("ectags");
7723 if(not $CTags) {
7724 printMsg("WARNING", "can't find \'ectags\' program");
7725 }
7726 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007727 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007728 $CTags = get_CmdPath("ctags");
7729 }
7730 if(not $CTags)
7731 {
7732 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007733 return;
7734 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007735
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007736 if($OSgroup ne "linux")
7737 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007738 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
7739 if($Info!~/exuberant/i)
7740 {
7741 printMsg("WARNING", "incompatible version of \'ctags\' program");
7742 return;
7743 }
7744 }
7745
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007746 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04007747 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007748 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007749 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007750 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007751 open(CTAGS, "<", $Out);
7752 while(my $Line = <CTAGS>)
7753 {
7754 chomp($Line);
7755 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007756 if(defined $Intrinsic_Keywords{$Name})
7757 { # noise
7758 next;
7759 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007760 if($Type eq "n")
7761 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007762 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007763 next;
7764 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007765 if(index($Scpe, "struct:")==0) {
7766 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007767 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007768 if(index($Scpe, "namespace:")==0)
7769 {
7770 if($Scpe=~s/\Anamespace://) {
7771 $Name = $Scpe."::".$Name;
7772 }
7773 }
7774 $TUnit_NameSpaces{$Version}{$Name} = 1;
7775 }
7776 elsif($Type eq "p")
7777 {
7778 if(not $Scpe or index($Scpe, "namespace:")==0) {
7779 $TUnit_Funcs{$Version}{$Name} = 1;
7780 }
7781 }
7782 elsif($Type eq "x")
7783 {
7784 if(not $Scpe or index($Scpe, "namespace:")==0) {
7785 $TUnit_Vars{$Version}{$Name} = 1;
7786 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007787 }
7788 }
7789 close(CTAGS);
7790}
7791
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007792sub preChange($$)
7793{
7794 my ($HeaderPath, $IncStr) = @_;
7795
7796 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
7797 my $Content = undef;
7798
7799 if($OStarget eq "windows"
7800 and get_dumpmachine($GCC_PATH)=~/mingw/i
7801 and $MinGWMode{$Version}!=-1)
7802 { # modify headers to compile by MinGW
7803 if(not $Content)
7804 { # preprocessing
7805 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
7806 }
7807 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
7808 { # __asm { ... }
7809 $MinGWMode{$Version}=1;
7810 }
7811 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
7812 { # comments after preprocessing
7813 $MinGWMode{$Version}=1;
7814 }
7815 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
7816 { # 0xffui8
7817 $MinGWMode{$Version}=1;
7818 }
7819
7820 if($MinGWMode{$Version}) {
7821 printMsg("INFO", "Using MinGW compatibility mode");
7822 }
7823 }
7824
7825 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
7826 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
7827 { # rename C++ keywords in C code
7828 # disable this code by -cpp-compatible option
7829 if(not $Content)
7830 { # preprocessing
7831 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
7832 }
7833 my $RegExp_C = join("|", keys(%CppKeywords_C));
7834 my $RegExp_F = join("|", keys(%CppKeywords_F));
7835 my $RegExp_O = join("|", keys(%CppKeywords_O));
7836
7837 my $Detected = undef;
7838
7839 while($Content=~s/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*(\,|\)|\;|\-\>|\.|\:\s*\d))/$1$2c99_$3$4/g)
7840 { # MATCH:
7841 # int foo(int new, int class, int (*new)(int));
7842 # unsigned private: 8;
7843 # DO NOT MATCH:
7844 # #pragma GCC visibility push(default)
7845 $CppMode{$Version} = 1;
7846 $Detected = "$1$2$3$4" if(not defined $Detected);
7847 }
7848 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
7849 { # MATCH:
7850 # int delete(...);
7851 # int explicit(...);
7852 # DO NOT MATCH:
7853 # void operator delete(...)
7854 $CppMode{$Version} = 1;
7855 $Detected = "$1$2$3" if(not defined $Detected);
7856 }
7857 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
7858 { # MATCH:
7859 # int bool;
7860 # DO NOT MATCH:
7861 # bool X;
7862 # return *this;
7863 # throw;
7864 $CppMode{$Version} = 1;
7865 $Detected = "$1$2$3" if(not defined $Detected);
7866 }
7867 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
7868 { # MATCH:
7869 # int operator(...);
7870 # DO NOT MATCH:
7871 # int operator()(...);
7872 $CppMode{$Version} = 1;
7873 $Detected = "$1$2$3" if(not defined $Detected);
7874 }
7875 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
7876 { # MATCH:
7877 # int foo(int operator);
7878 # int foo(int operator, int other);
7879 # DO NOT MATCH:
7880 # int operator,(...);
7881 $CppMode{$Version} = 1;
7882 $Detected = "$1$2$3" if(not defined $Detected);
7883 }
7884 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
7885 { # MATCH:
7886 # int foo(gboolean *bool);
7887 # DO NOT MATCH:
7888 # void setTabEnabled(int index, bool);
7889 $CppMode{$Version} = 1;
7890 $Detected = "$1$2$3" if(not defined $Detected);
7891 }
7892 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
7893 { # MATCH:
7894 # int foo(int* this);
7895 # int bar(int this);
7896 # int baz(int throw);
7897 # DO NOT MATCH:
7898 # foo(X, this);
7899 $CppMode{$Version} = 1;
7900 $Detected = "$1$2$3$4" if(not defined $Detected);
7901 }
7902 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
7903 { # MATCH:
7904 # struct template {...};
7905 # extern template foo(...);
7906 $CppMode{$Version} = 1;
7907 $Detected = "$1$2" if(not defined $Detected);
7908 }
7909
7910 if($CppMode{$Version} == 1)
7911 {
7912 if($Debug)
7913 {
7914 $Detected=~s/\A\s+//g;
7915 printMsg("INFO", "Detected code: \"$Detected\"");
7916 }
7917 }
7918
7919 # remove typedef enum NAME NAME;
7920 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
7921 my $N = 0;
7922 while($N<=$#FwdTypedefs-1)
7923 {
7924 my $S = $FwdTypedefs[$N];
7925 if($S eq $FwdTypedefs[$N+1])
7926 {
7927 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007928 $CppMode{$Version} = 1;
7929
7930 if($Debug) {
7931 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
7932 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007933 }
7934 $N+=2;
7935 }
7936
7937 if($CppMode{$Version}==1) {
7938 printMsg("INFO", "Using C++ compatibility mode");
7939 }
7940 }
7941
7942 if($CppMode{$Version}==1
7943 or $MinGWMode{$Version}==1)
7944 {
7945 my $IPath = $TMP_DIR."/dump$Version.i";
7946 writeFile($IPath, $Content);
7947 return $IPath;
7948 }
7949
7950 return undef;
7951}
7952
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04007953sub getDump()
7954{
7955 if(not $GCC_PATH) {
7956 exitStatus("Error", "internal error - GCC path is not set");
7957 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007958
7959 my @Headers = keys(%{$Registered_Headers{$Version}});
7960 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
7961
7962 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
7963
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007964 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007965 my $HeaderPath = $TmpHeaderPath;
7966
7967 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007968 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007969 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
7970 {
7971 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007972 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007973 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007974 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007975 foreach my $HPath (@{$Include_Preamble{$Version}}) {
7976 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007977 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007978 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007979 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007980 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
7981 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
7982 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007983 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04007984 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007985
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007986 if($ExtraInfo)
7987 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007988 if($IncludeString) {
7989 writeFile($ExtraInfo."/include-string", $IncludeString);
7990 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04007991 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
7992 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007993
7994 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
7995 {
7996 my $REDIR = "";
7997 foreach my $P1 (sort @Redirects) {
7998 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
7999 }
8000 writeFile($ExtraInfo."/include-redirect", $REDIR);
8001 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008002 }
8003
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008004 if(not keys(%{$TargetHeaders{$Version}}))
8005 { # Target headers
8006 addTargetHeaders($Version);
8007 }
8008
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008009 # clean memory
8010 %RecursiveIncludes = ();
8011 %Header_Include_Prefix = ();
8012 %Header_Includes = ();
8013
8014 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008015 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008016 delete($Cache{"detect_header_includes"});
8017 delete($Cache{"selectSystemHeader"});
8018
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008019 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008020 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8021 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008022
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008023 if($ExtraInfo)
8024 { # extra information for other tools
8025 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8026 }
8027
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008028 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008029 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008030 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008031
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008032 if($COMMON_LANGUAGE{$Version} eq "C++") {
8033 checkCTags($Pre);
8034 }
8035
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008036 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8037 { # try to correct the preprocessor output
8038 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008039 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008040
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008041 if($COMMON_LANGUAGE{$Version} eq "C++")
8042 { # add classes and namespaces to the dump
8043 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008044 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008045 or $MinGWMode{$Version}==1) {
8046 $CHdump .= " -fpreprocessed";
8047 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008048 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008049 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008050 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008051 chdir($ORIG_DIR);
8052 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8053 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008054 my $Content = readFile($ClassDump);
8055 foreach my $ClassInfo (split(/\n\n/, $Content))
8056 {
8057 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8058 {
8059 my $CName = $1;
8060 next if($CName=~/\A(__|_objc_|_opaque_)/);
8061 $TUnit_NameSpaces{$Version}{$CName} = -1;
8062 if($CName=~/\A[\w:]+\Z/)
8063 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008064 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008065 }
8066 if($CName=~/(\w[\w:]*)::/)
8067 { # namespaces
8068 my $NS = $1;
8069 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8070 $TUnit_NameSpaces{$Version}{$NS} = 1;
8071 }
8072 }
8073 }
8074 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8075 { # read v-tables (advanced approach)
8076 my ($CName, $VTable) = ($1, $2);
8077 $ClassVTable_Content{$Version}{$CName} = $VTable;
8078 }
8079 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008080 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8081 { # add user-defined namespaces
8082 $TUnit_NameSpaces{$Version}{$NS} = 1;
8083 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008084 if($Debug)
8085 { # debug mode
8086 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008087 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008088 }
8089 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008090 }
8091
8092 # add namespaces and classes
8093 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8094 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008095 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008096 }
8097 # some GCC versions don't include class methods to the TU dump by default
8098 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008099 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008100 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8101 {
8102 next if($C_Structure{$CName});
8103 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008104 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008105 if(not $Force and $GCC_44
8106 and $OSgroup eq "linux")
8107 { # optimization for linux with GCC >= 4.4
8108 # disable this code by -force option
8109 if(index($CName, "::")!=-1)
8110 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008111 next;
8112 }
8113 }
8114 else
8115 {
8116 if($CName=~/\A(.+)::[^:]+\Z/
8117 and $TUnit_Classes{$Version}{$1})
8118 { # classes inside other classes
8119 next;
8120 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008121 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008122 if(defined $TUnit_Funcs{$Version}{$CName})
8123 { # the same name for a function and type
8124 next;
8125 }
8126 if(defined $TUnit_Vars{$Version}{$CName})
8127 { # the same name for a variable and type
8128 next;
8129 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008130 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8131 }
8132 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008133 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008134 }
8135 }
8136 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8137 # create TU dump
8138 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008139 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008140 or $MinGWMode{$Version}==1) {
8141 $TUdump .= " -fpreprocessed";
8142 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008143 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008144 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8145 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008146 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008147 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008148 if($?)
8149 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008150 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008151 { # try to recompile
8152 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008153 if($CppMode{$Version}==1
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008154 and index($Errors, "c99_")!=-1)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008155 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008156 $CppMode{$Version}=-1;
8157 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008158 resetLogging($Version);
8159 $TMP_DIR = tempdir(CLEANUP=>1);
8160 return getDump();
8161 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008162 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008163 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008164 { # add auto preamble headers and try again
8165 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008166 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008167 foreach my $Num (0 .. $#Headers)
8168 {
8169 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008170 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8171 {
8172 push_U($Include_Preamble{$Version}, $Path);
8173 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008174 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008175 }
8176 resetLogging($Version);
8177 $TMP_DIR = tempdir(CLEANUP=>1);
8178 return getDump();
8179 }
8180 elsif($Cpp0xMode{$Version}!=-1
8181 and ($Errors=~/\Q-std=c++0x\E/
8182 or $Errors=~/is not a class or namespace/))
8183 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008184 if(check_gcc($GCC_PATH, "4.6"))
8185 {
8186 $Cpp0xMode{$Version}=-1;
8187 printMsg("INFO", "Enabling c++0x mode");
8188 resetLogging($Version);
8189 $TMP_DIR = tempdir(CLEANUP=>1);
8190 $CompilerOptions{$Version} .= " -std=c++0x";
8191 return getDump();
8192 }
8193 else {
8194 printMsg("WARNING", "Probably c++0x construction detected");
8195 }
8196
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008197 }
8198 elsif($MinGWMode{$Version}==1)
8199 { # disable MinGW mode and try again
8200 $MinGWMode{$Version}=-1;
8201 resetLogging($Version);
8202 $TMP_DIR = tempdir(CLEANUP=>1);
8203 return getDump();
8204 }
8205 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008206 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008207 else {
8208 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008209 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008210 printMsg("ERROR", "some errors occurred when compiling headers");
8211 printErrorLog($Version);
8212 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008213 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008214 }
8215 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008216 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008217 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008218
8219 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8220 return $TUs[0];
8221 }
8222 else
8223 {
8224 my $Msg = "can't compile header(s)";
8225 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8226 $Msg .= "\nDid you install G++?";
8227 }
8228 exitStatus("Cannot_Compile", $Msg);
8229 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008230}
8231
8232sub cmd_file($)
8233{
8234 my $Path = $_[0];
8235 return "" if(not $Path or not -e $Path);
8236 if(my $CmdPath = get_CmdPath("file")) {
8237 return `$CmdPath -b \"$Path\"`;
8238 }
8239 return "";
8240}
8241
8242sub getIncString($$)
8243{
8244 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008245 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008246 my $String = "";
8247 foreach (@{$ArrRef}) {
8248 $String .= " ".inc_opt($_, $Style);
8249 }
8250 return $String;
8251}
8252
8253sub getIncPaths(@)
8254{
8255 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008256 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008257 if($INC_PATH_AUTODETECT{$Version})
8258 { # auto-detecting dependencies
8259 my %Includes = ();
8260 foreach my $HPath (@HeaderPaths)
8261 {
8262 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8263 {
8264 if($Skip_Include_Paths{$Version}{$Dir}) {
8265 next;
8266 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008267 if($SystemRoot)
8268 {
8269 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8270 next;
8271 }
8272 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008273 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008274 }
8275 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008276 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008277 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008278 }
8279 }
8280 else
8281 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008282 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008283 }
8284 return \@IncPaths;
8285}
8286
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008287sub push_U($@)
8288{ # push unique
8289 if(my $Array = shift @_)
8290 {
8291 if(@_)
8292 {
8293 my %Exist = map {$_=>1} @{$Array};
8294 foreach my $Elem (@_)
8295 {
8296 if(not defined $Exist{$Elem})
8297 {
8298 push(@{$Array}, $Elem);
8299 $Exist{$Elem} = 1;
8300 }
8301 }
8302 }
8303 }
8304}
8305
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008306sub callPreprocessor($$$)
8307{
8308 my ($Path, $Inc, $LibVersion) = @_;
8309 return "" if(not $Path or not -f $Path);
8310 my $IncludeString=$Inc;
8311 if(not $Inc) {
8312 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8313 }
8314 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008315 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008316 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008317 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008318}
8319
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008320sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008321{ # native "find" is much faster than File::Find (~6x)
8322 # also the File::Find doesn't support --maxdepth N option
8323 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008324 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008325 return () if(not $Path or not -e $Path);
8326 if($OSgroup eq "windows")
8327 {
8328 my $DirCmd = get_CmdPath("dir");
8329 if(not $DirCmd) {
8330 exitStatus("Not_Found", "can't find \"dir\" command");
8331 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008332 $Path = get_abs_path($Path);
8333 $Path = path_format($Path, $OSgroup);
8334 my $Cmd = $DirCmd." \"$Path\" /B /O";
8335 if($MaxDepth!=1) {
8336 $Cmd .= " /S";
8337 }
8338 if($Type eq "d") {
8339 $Cmd .= " /AD";
8340 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008341 elsif($Type eq "f") {
8342 $Cmd .= " /A-D";
8343 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008344 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008345 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008346 {
8347 if(not $UseRegex)
8348 { # FIXME: how to search file names in MS shell?
8349 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008350 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008351 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008352 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008353 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008354 }
8355 my @AbsPaths = ();
8356 foreach my $File (@Files)
8357 {
8358 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008359 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008360 }
8361 if($Type eq "f" and not -f $File)
8362 { # skip dirs
8363 next;
8364 }
8365 push(@AbsPaths, path_format($File, $OSgroup));
8366 }
8367 if($Type eq "d") {
8368 push(@AbsPaths, $Path);
8369 }
8370 return @AbsPaths;
8371 }
8372 else
8373 {
8374 my $FindCmd = get_CmdPath("find");
8375 if(not $FindCmd) {
8376 exitStatus("Not_Found", "can't find a \"find\" command");
8377 }
8378 $Path = get_abs_path($Path);
8379 if(-d $Path and -l $Path
8380 and $Path!~/\/\Z/)
8381 { # for directories that are symlinks
8382 $Path.="/";
8383 }
8384 my $Cmd = $FindCmd." \"$Path\"";
8385 if($MaxDepth) {
8386 $Cmd .= " -maxdepth $MaxDepth";
8387 }
8388 if($Type) {
8389 $Cmd .= " -type $Type";
8390 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008391 if($Name and not $UseRegex)
8392 { # wildcards
8393 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008394 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008395 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008396 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008397 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8398 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008399 my @Files = split(/\n/, $Res);
8400 if($Name and $UseRegex)
8401 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008402 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008403 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008404 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008405 }
8406}
8407
8408sub unpackDump($)
8409{
8410 my $Path = $_[0];
8411 return "" if(not $Path or not -e $Path);
8412 $Path = get_abs_path($Path);
8413 $Path = path_format($Path, $OSgroup);
8414 my ($Dir, $FileName) = separate_path($Path);
8415 my $UnpackDir = $TMP_DIR."/unpack";
8416 rmtree($UnpackDir);
8417 mkpath($UnpackDir);
8418 if($FileName=~s/\Q.zip\E\Z//g)
8419 { # *.zip
8420 my $UnzipCmd = get_CmdPath("unzip");
8421 if(not $UnzipCmd) {
8422 exitStatus("Not_Found", "can't find \"unzip\" command");
8423 }
8424 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008425 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008426 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008427 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008428 }
8429 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008430 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008431 if(not @Contents) {
8432 exitStatus("Error", "can't extract \'$Path\'");
8433 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008434 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008435 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008436 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008437 { # *.tar.gz
8438 if($OSgroup eq "windows")
8439 { # -xvzf option is not implemented in tar.exe (2003)
8440 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8441 my $TarCmd = get_CmdPath("tar");
8442 if(not $TarCmd) {
8443 exitStatus("Not_Found", "can't find \"tar\" command");
8444 }
8445 my $GzipCmd = get_CmdPath("gzip");
8446 if(not $GzipCmd) {
8447 exitStatus("Not_Found", "can't find \"gzip\" command");
8448 }
8449 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008450 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008451 if($?) {
8452 exitStatus("Error", "can't extract \'$Path\'");
8453 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008454 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008455 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008456 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008457 }
8458 chdir($ORIG_DIR);
8459 unlink($Dir."/".$FileName.".tar");
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 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008467 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008468 my $TarCmd = get_CmdPath("tar");
8469 if(not $TarCmd) {
8470 exitStatus("Not_Found", "can't find \"tar\" command");
8471 }
8472 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008473 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008474 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008475 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008476 }
8477 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008478 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008479 if(not @Contents) {
8480 exitStatus("Error", "can't extract \'$Path\'");
8481 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008482 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008483 }
8484 }
8485}
8486
8487sub createArchive($$)
8488{
8489 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008490 if(not $To) {
8491 $To = ".";
8492 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008493 if(not $Path or not -e $Path
8494 or not -d $To) {
8495 return "";
8496 }
8497 my ($From, $Name) = separate_path($Path);
8498 if($OSgroup eq "windows")
8499 { # *.zip
8500 my $ZipCmd = get_CmdPath("zip");
8501 if(not $ZipCmd) {
8502 exitStatus("Not_Found", "can't find \"zip\"");
8503 }
8504 my $Pkg = $To."/".$Name.".zip";
8505 unlink($Pkg);
8506 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008507 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008508 if($?)
8509 { # cannot allocate memory (or other problems with "zip")
8510 unlink($Path);
8511 exitStatus("Error", "can't pack the ABI dump: ".$!);
8512 }
8513 chdir($ORIG_DIR);
8514 unlink($Path);
8515 return $Pkg;
8516 }
8517 else
8518 { # *.tar.gz
8519 my $TarCmd = get_CmdPath("tar");
8520 if(not $TarCmd) {
8521 exitStatus("Not_Found", "can't find \"tar\"");
8522 }
8523 my $GzipCmd = get_CmdPath("gzip");
8524 if(not $GzipCmd) {
8525 exitStatus("Not_Found", "can't find \"gzip\"");
8526 }
8527 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8528 unlink($Pkg);
8529 chdir($From);
8530 system($TarCmd, "-czf", $Pkg, $Name);
8531 if($?)
8532 { # cannot allocate memory (or other problems with "tar")
8533 unlink($Path);
8534 exitStatus("Error", "can't pack the ABI dump: ".$!);
8535 }
8536 chdir($ORIG_DIR);
8537 unlink($Path);
8538 return $To."/".$Name.".tar.gz";
8539 }
8540}
8541
8542sub is_header_file($)
8543{
8544 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
8545 return $_[0];
8546 }
8547 return 0;
8548}
8549
8550sub is_not_header($)
8551{
8552 if($_[0]=~/\.\w+\Z/
8553 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
8554 return 1;
8555 }
8556 return 0;
8557}
8558
8559sub is_header($$$)
8560{
8561 my ($Header, $UserDefined, $LibVersion) = @_;
8562 return 0 if(-d $Header);
8563 if(-f $Header) {
8564 $Header = get_abs_path($Header);
8565 }
8566 else
8567 {
8568 if(is_abs($Header))
8569 { # incorrect absolute path
8570 return 0;
8571 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008572 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008573 $Header = $HPath;
8574 }
8575 else
8576 { # can't find header
8577 return 0;
8578 }
8579 }
8580 if($Header=~/\.\w+\Z/)
8581 { # have an extension
8582 return is_header_file($Header);
8583 }
8584 else
8585 {
8586 if($UserDefined==2)
8587 { # specified on the command line
8588 if(cmd_file($Header)!~/HTML|XML/i) {
8589 return $Header;
8590 }
8591 }
8592 elsif($UserDefined)
8593 { # specified in the XML-descriptor
8594 # header file without an extension
8595 return $Header;
8596 }
8597 else
8598 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008599 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008600 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008601 { # !~/HTML|XML|shared|dynamic/i
8602 return $Header;
8603 }
8604 }
8605 }
8606 return 0;
8607}
8608
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008609sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008610{
8611 my $LibVersion = $_[0];
8612 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
8613 {
8614 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008615 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008616
8617 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
8618 detect_recursive_includes($RegHeader, $LibVersion);
8619 }
8620
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008621 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
8622 {
8623 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008624
8625 if(familiarDirs($Dir, $RegDir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008626 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
8627 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008628 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008629 }
8630 }
8631 }
8632}
8633
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008634sub familiarDirs($$)
8635{
8636 my ($D1, $D2) = @_;
8637 if($D1 eq $D2) {
8638 return 1;
8639 }
8640 while($D1=~s/[\/\\]+.*?\Z//)
8641 {
8642 $D2=~s/[\/\\]+.*?\Z//;
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04008643 if(not $D1 or not $D2) {
8644 return 0;
8645 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008646 if($D1 eq "/usr/include") {
8647 return 0;
8648 }
8649 if($D1 eq $D2) {
8650 return 1;
8651 }
8652 }
8653 return 0;
8654}
8655
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008656sub readHeaders($)
8657{
8658 $Version = $_[0];
8659 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
8660 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008661 if($Debug)
8662 { # debug mode
8663 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008664 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008665 }
8666 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008667}
8668
8669sub prepareTypes($)
8670{
8671 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008672 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008673 { # support for old ABI dumps
8674 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008675 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008676 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008677 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
8678 if($TName=~/\A(\w+)::(\w+)/) {
8679 my ($P1, $P2) = ($1, $2);
8680 if($P1 eq $P2) {
8681 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008682 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008683 else {
8684 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
8685 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008686 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008687 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008688 }
8689 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008690 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008691 { # support for old ABI dumps
8692 # V < 2.5: array size == "number of elements"
8693 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008694 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008695 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008696 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008697 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008698 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008699 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008700 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008701 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008702 $Size *= $Base{"Size"};
8703 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008704 }
8705 else
8706 { # array[] is a pointer
8707 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008708 }
8709 }
8710 }
8711 }
8712 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008713 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008714 { # support for old ABI dumps
8715 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008716 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008717 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008718 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008719 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008720 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008721 my %Type = get_Type($TypeId, $LibVersion);
8722 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
8723 my %Type2 = get_Type($TypeId_2, $V2);
8724 if($Type{"Size"} ne $Type2{"Size"}) {
8725 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008726 }
8727 }
8728 }
8729 }
8730}
8731
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008732sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008733{
8734 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008735
8736 if(not keys(%{$SymbolInfo{$LibVersion}}))
8737 { # check if input is valid
8738 if(not $ExtendedCheck and not $CheckObjectsOnly)
8739 {
8740 if($CheckHeadersOnly) {
8741 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
8742 }
8743 else {
8744 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
8745 }
8746 }
8747 }
8748
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008749 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008750 if(not checkDump(1, "2.10")
8751 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008752 { # different formats
8753 $Remangle = 1;
8754 }
8755 if($CheckHeadersOnly)
8756 { # different languages
8757 if($UserLang)
8758 { # --lang=LANG for both versions
8759 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
8760 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
8761 {
8762 if($UserLang eq "C++")
8763 { # remangle symbols
8764 $Remangle = 1;
8765 }
8766 elsif($UserLang eq "C")
8767 { # remove mangling
8768 $Remangle = -1;
8769 }
8770 }
8771 }
8772 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008773
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008774 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008775 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008776 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04008777 { # support for old ABI dumps
8778 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
8779 {
8780 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
8781 {
8782 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
8783 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008784 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04008785 if(defined $DVal and $DVal ne "")
8786 {
8787 if($TName eq "char") {
8788 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
8789 }
8790 elsif($TName eq "bool") {
8791 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
8792 }
8793 }
8794 }
8795 }
8796 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008797 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008798 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008799 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
8800 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008801 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008802 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
8803 # + support for old ABI dumps
8804 next;
8805 }
8806 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008807 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008808 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008809 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008810 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008811
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008812 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008813 if(not checkDump(1, "2.12")
8814 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008815 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008816 if($ShortName eq "operator>>")
8817 {
8818 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
8819 { # corrected mangling of operator>>
8820 $SRemangle = 1;
8821 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008822 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008823 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
8824 {
8825 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
8826 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
8827 { # corrected mangling of const global data
8828 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
8829 # and incorrectly mangled by old ACC versions
8830 $SRemangle = 1;
8831 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008832 }
8833 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008834 if(not $CheckHeadersOnly)
8835 { # support for old ABI dumps
8836 if(not checkDump(1, "2.17")
8837 or not checkDump(2, "2.17"))
8838 {
8839 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
8840 {
8841 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
8842 {
8843 if(link_symbol($ShortName, $LibVersion, "-Deps"))
8844 {
8845 $MnglName = $ShortName;
8846 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
8847 }
8848 }
8849 }
8850 }
8851 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008852 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008853 { # support for old ABI dumps: some symbols are not mangled in old dumps
8854 # mangle both sets of symbols (old and new)
8855 # NOTE: remangling all symbols by the same mangler
8856 if($MnglName=~/\A_ZN(V|)K/)
8857 { # mangling may be incorrect on old ABI dumps
8858 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008859 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008860 }
8861 if($MnglName=~/\A_ZN(K|)V/)
8862 { # mangling may be incorrect on old ABI dumps
8863 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008864 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008865 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008866 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
8867 or (not $ClassID and $CheckHeadersOnly)
8868 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
8869 { # support for old ABI dumps, GCC >= 4.0
8870 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008871 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008872 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008873 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008874 $MangledNames{$LibVersion}{$MnglName} = 1;
8875 }
8876 }
8877 }
8878 elsif($Remangle==-1)
8879 { # remove mangling
8880 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008881 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008882 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008883 if(not $MnglName) {
8884 next;
8885 }
8886 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
8887 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008888 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
8889
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008890 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008891 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008892 { # support for old dumps
8893 # add "Volatile" attribute
8894 if($MnglName=~/_Z(K|)V/) {
8895 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
8896 }
8897 }
8898 # symbol and its symlink have same signatures
8899 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008900 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008901 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008902
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008903 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
8904 {
8905 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
8906 if($SymVer{$LibVersion}{$Alias}) {
8907 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
8908 }
8909 }
8910
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008911 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008912 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008913 }
8914 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
8915 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
8916 }
8917 if($ExtendedCheck)
8918 { # --ext option
8919 addExtension($LibVersion);
8920 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008921
8922 # clean memory
8923 delete($SymbolInfo{$LibVersion});
8924
8925 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008926 { # detect allocable classes with public exported constructors
8927 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008928 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008929 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008930 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008931 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008932 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
8933 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008934 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008935 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008936 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008937 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008938 $AllocableClass{$LibVersion}{$ClassName} = 1;
8939 }
8940 }
8941 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008942 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008943 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008944 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008945 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008946 if($CheckHeadersOnly)
8947 {
8948 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
8949 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
8950 { # all symbols except non-virtual inline
8951 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
8952 }
8953 }
8954 else {
8955 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008956 }
8957 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008958 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008959 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008960 }
8961 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008962 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008963 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008964 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008965 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008966 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008967 if(defined $Base{"Type"}
8968 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008969 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008970 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008971 if($Name=~/<([^<>\s]+)>/)
8972 {
8973 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
8974 $ReturnedClass{$LibVersion}{$Tid} = 1;
8975 }
8976 }
8977 else {
8978 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
8979 }
8980 }
8981 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008982 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008983 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008984 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008985 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008986 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008987 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008988 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008989 if($Base{"Type"}=~/Struct|Class/)
8990 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008991 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008992 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
8993 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008994 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04008995 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008996 }
8997 }
8998 }
8999 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009000
9001 # mapping {short name => symbols}
9002 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009003 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009004 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009005 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009006 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009007 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009008 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009009 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009010 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9011 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009012 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009013 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009014 }
9015 }
9016 }
9017 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009018
9019 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009020 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009021 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009022 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009023 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009024 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9025 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009026 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009027 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009028 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009029 $ClassNames{$LibVersion}{$TName} = 1;
9030 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009031 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009032 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9033 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009034 }
9035 }
9036 }
9037 }
9038 }
9039}
9040
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009041sub register_TypeUsage($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009042{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009043 my ($TypeId, $LibVersion) = @_;
9044 if(not $TypeId) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009045 return 0;
9046 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009047 if($UsedType{$LibVersion}{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009048 { # already registered
9049 return 1;
9050 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009051 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009052 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009053 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009054 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|MethodPtr|FieldPtr|Enum)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009055 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009056 $UsedType{$LibVersion}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009057 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009058 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009059 foreach my $BaseId (keys(%{$TInfo{"Base"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009060 { # register base classes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009061 register_TypeUsage($BaseId, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009062 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009063 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9064 {
9065 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9066 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009067 register_TypeUsage($TTid, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009068 }
9069 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009070 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009071 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009072 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009073 if(my $MTid = $TInfo{"Memb"}{$Memb_Pos}{"type"}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009074 register_TypeUsage($MTid, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009075 }
9076 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009077 if($TInfo{"Type"} eq "FuncPtr"
9078 or $TInfo{"Type"} eq "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009079 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009080 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009081 register_TypeUsage($RTid, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009082 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009083 foreach my $Memb_Pos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009084 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009085 if(my $MTid = $TInfo{"Param"}{$Memb_Pos}{"type"}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009086 register_TypeUsage($MTid, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009087 }
9088 }
9089 }
9090 return 1;
9091 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009092 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009093 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009094 $UsedType{$LibVersion}{$TypeId} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009095 register_TypeUsage($TInfo{"BaseType"}, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009096 return 1;
9097 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009098 elsif($TInfo{"Type"} eq "Intrinsic")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009099 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009100 $UsedType{$LibVersion}{$TypeId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009101 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009102 }
9103 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009104 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009105}
9106
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009107sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009108{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009109 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9110
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009111 if($Level eq "Dump")
9112 {
9113 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9114 { # TODO: check if this symbol is from
9115 # base classes of other target symbols
9116 return 1;
9117 }
9118 }
9119
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009120 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9121 { # stdc++ interfaces
9122 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009123 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009124
9125 my $Target = 0;
9126 if(my $Header = $SInfo->{"Header"}) {
9127 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9128 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009129 if($ExtendedCheck)
9130 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009131 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009132 $Target = 1;
9133 }
9134 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009135 if($CheckHeadersOnly)
9136 {
9137 if($Target)
9138 {
9139 if($Level eq "Dump")
9140 { # dumped
9141 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009142 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009143 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009144 return 1;
9145 }
9146 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009147 else {
9148 return 1;
9149 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009150 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009151 elsif($Level eq "Source")
9152 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009153 return 1;
9154 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009155 elsif($Level eq "Binary")
9156 { # checked
9157 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9158 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9159 return 1;
9160 }
9161 }
9162 }
9163 }
9164 else
9165 { # library is available
9166 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9167 { # exported symbols
9168 return 1;
9169 }
9170 if($Level eq "Dump")
9171 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009172 if($BinaryOnly)
9173 {
9174 if($SInfo->{"Data"})
9175 {
9176 if($Target) {
9177 return 1;
9178 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009179 }
9180 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009181 else
9182 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009183 if($Target) {
9184 return 1;
9185 }
9186 }
9187 }
9188 elsif($Level eq "Source")
9189 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009190 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
9191 or isInLineInst($Symbol, $SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009192 { # skip LOCAL symbols
9193 if($Target) {
9194 return 1;
9195 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009196 }
9197 }
9198 elsif($Level eq "Binary")
9199 { # checked
9200 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9201 {
9202 if($Target) {
9203 return 1;
9204 }
9205 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009206 }
9207 }
9208 return 0;
9209}
9210
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009211sub cleanDump($)
9212{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009213 my $LibVersion = $_[0];
9214 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9215 {
9216 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
9217 if(not $MnglName) {
9218 delete($SymbolInfo{$LibVersion}{$InfoId});
9219 next;
9220 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009221 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009222 if(not $ShortName) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009223 delete($SymbolInfo{$LibVersion}{$InfoId});
9224 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009225 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009226 if($MnglName eq $ShortName)
9227 { # remove duplicate data
9228 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009229 }
9230 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9231 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9232 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009233 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9234 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9235 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009236 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009237 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009238 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009239 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009240 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009241 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009242 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9243 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9244 }
9245 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009246 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9247 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9248 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009249 }
9250}
9251
9252sub selectType($$)
9253{
9254 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009255
9256 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9257 {
9258 if(defined $TypeInfo{$LibVersion}{$Dupl})
9259 {
9260 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9261 { # duplicate
9262 return 0;
9263 }
9264 }
9265 }
9266
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009267 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9268 {
9269 if(not isBuiltIn($THeader))
9270 {
9271 if($TypeInfo{$LibVersion}{$Tid}{"Type"}=~/Class|Struct|Union|Enum|Typedef/)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009272 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009273 if(not isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"}))
9274 {
9275 if(is_target_header($THeader, $LibVersion))
9276 { # from target headers
9277 if(not selfTypedef($Tid, $LibVersion)) {
9278 return 1;
9279 }
9280 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009281 }
9282 }
9283 }
9284 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009285 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009286}
9287
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009288sub removeUnused($$)
9289{ # remove unused data types from the ABI dump
9290 my ($LibVersion, $Kind) = @_;
9291 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9292 {
9293 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9294 if(my $RTid = $FuncInfo{"Return"}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009295 register_TypeUsage($RTid, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009296 }
9297 if(my $FCid = $FuncInfo{"Class"})
9298 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009299 register_TypeUsage($FCid, $LibVersion);
9300 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009301 { # register "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009302 $UsedType{$LibVersion}{$ThisId} = 1;
9303 if(my %ThisType = get_Type($ThisId, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009304 register_TypeUsage($ThisType{"BaseType"}, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009305 }
9306 }
9307 }
9308 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9309 {
9310 if(my $PTid = $FuncInfo{"Param"}{$PPos}{"type"}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009311 register_TypeUsage($PTid, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009312 }
9313 }
9314 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9315 {
9316 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9317 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009318 register_TypeUsage($TTid, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009319 }
9320 }
9321 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009322 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
9323 {
9324 if($UsedType{$LibVersion}{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009325 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009326 next;
9327 }
9328
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009329 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009330 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009331 if(selectType($Tid, $LibVersion)) {
9332 register_TypeUsage($Tid, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009333 }
9334 }
9335 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009336 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
9337 { # remove unused types
9338 if($UsedType{$LibVersion}{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009339 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009340 next;
9341 }
9342 # remove type
9343 delete($TypeInfo{$LibVersion}{$Tid});
9344 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009345
9346 # clean memory
9347 %UsedType = ();
9348}
9349
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009350sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009351{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009352 my ($TypeId, $LibVersion) = @_;
9353 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009354 if($Type{"Type"} eq "Typedef")
9355 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009356 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009357 if($Base{"Type"}=~/Class|Struct/)
9358 {
9359 if($Type{"Name"} eq $Base{"Name"}) {
9360 return 1;
9361 }
9362 elsif($Type{"Name"}=~/::(\w+)\Z/)
9363 {
9364 if($Type{"Name"} eq $Base{"Name"}."::".$1)
9365 { # QPointer<QWidget>::QPointer
9366 return 1;
9367 }
9368 }
9369 }
9370 }
9371 return 0;
9372}
9373
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009374sub addExtension($)
9375{
9376 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009377 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009378 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009379 if(selectType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009380 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009381 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9382 $TName=~s/\A(struct|union|class|enum) //;
9383 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009384
9385 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
9386 "Header" => "extended.h",
9387 "ShortName" => $Symbol,
9388 "MnglName" => $Symbol,
9389 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
9390 );
9391
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009392 $ExtendedSymbols{$Symbol} = 1;
9393 $CheckedSymbols{"Binary"}{$Symbol} = 1;
9394 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009395 }
9396 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009397 $ExtendedSymbols{"external_func_0"} = 1;
9398 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
9399 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009400}
9401
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009402sub findMethod($$$)
9403{
9404 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009405 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009406 {
9407 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
9408 return $VirtMethodInClass;
9409 }
9410 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
9411 return $VirtMethodInBaseClasses;
9412 }
9413 }
9414 return "";
9415}
9416
9417sub findMethod_Class($$$)
9418{
9419 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009420 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009421 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
9422 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
9423 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
9424 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
9425 { # search for interface with the same parameters suffix (overridden)
9426 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
9427 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04009428 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
9429 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009430 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
9431 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009432 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
9433 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
9434 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
9435 return $Candidate;
9436 }
9437 }
9438 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04009439 else
9440 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009441 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
9442 return $Candidate;
9443 }
9444 }
9445 }
9446 }
9447 return "";
9448}
9449
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009450sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009451{
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009452 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009453 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009454 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009455 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
9456 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009457 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009458 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009459 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009460 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
9461 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009462 { # pure virtual D2-destructors are marked as "virt" in the dump
9463 # virtual D2-destructors are NOT marked as "virt" in the dump
9464 # both destructors are not presented in the v-table
9465 next;
9466 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009467 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009468 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
9469 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009470 }
9471}
9472
9473sub registerOverriding($)
9474{
9475 my $LibVersion = $_[0];
9476 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009477 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009478 foreach my $ClassName (@Classes)
9479 {
9480 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
9481 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009482 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
9483 { # pure virtuals
9484 next;
9485 }
9486 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
9487 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009488 {
9489 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
9490 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
9491 { # both overridden virtual methods
9492 # and implemented pure virtual methods
9493 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
9494 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
9495 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
9496 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009497 }
9498 }
9499 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
9500 delete($VirtualTable{$LibVersion}{$ClassName});
9501 }
9502 }
9503}
9504
9505sub setVirtFuncPositions($)
9506{
9507 my $LibVersion = $_[0];
9508 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
9509 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009510 my ($Num, $Rel) = (1, 0);
9511
9512 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009513 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009514 if($UsedDump{$LibVersion}{"DWARF"}) {
9515 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
9516 }
9517 else {
9518 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
9519 }
9520 foreach my $VirtFunc (@Funcs)
9521 {
9522 if($UsedDump{$LibVersion}{"DWARF"}) {
9523 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
9524 }
9525 else {
9526 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
9527 }
9528
9529 # set relative positions
9530 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
9531 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
9532 { # relative position excluding added and removed virtual functions
9533 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
9534 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
9535 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
9536 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009537 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009538 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009539 }
9540 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009541 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009542 {
9543 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009544 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009545 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009546 }
9547 }
9548}
9549
9550sub get_sub_classes($$$)
9551{
9552 my ($ClassId, $LibVersion, $Recursive) = @_;
9553 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
9554 my @Subs = ();
9555 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
9556 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009557 if($Recursive)
9558 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009559 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
9560 push(@Subs, $SubSubId);
9561 }
9562 }
9563 push(@Subs, $SubId);
9564 }
9565 return @Subs;
9566}
9567
9568sub get_base_classes($$$)
9569{
9570 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009571 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009572 return () if(not defined $ClassType{"Base"});
9573 my @Bases = ();
9574 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
9575 keys(%{$ClassType{"Base"}}))
9576 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009577 if($Recursive)
9578 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009579 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
9580 push(@Bases, $SubBaseId);
9581 }
9582 }
9583 push(@Bases, $BaseId);
9584 }
9585 return @Bases;
9586}
9587
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009588sub getVTable_Model($$)
9589{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009590 my ($ClassId, $LibVersion) = @_;
9591 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
9592 my @Elements = ();
9593 foreach my $BaseId (@Bases, $ClassId)
9594 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009595 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009596 {
9597 if(defined $VirtualTable{$LibVersion}{$BName})
9598 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009599 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
9600 if($UsedDump{$LibVersion}{"DWARF"}) {
9601 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
9602 }
9603 else {
9604 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
9605 }
9606 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009607 push(@Elements, $VFunc);
9608 }
9609 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009610 }
9611 }
9612 return @Elements;
9613}
9614
9615sub getVShift($$)
9616{
9617 my ($ClassId, $LibVersion) = @_;
9618 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
9619 my $VShift = 0;
9620 foreach my $BaseId (@Bases)
9621 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009622 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009623 {
9624 if(defined $VirtualTable{$LibVersion}{$BName}) {
9625 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
9626 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009627 }
9628 }
9629 return $VShift;
9630}
9631
9632sub getShift($$)
9633{
9634 my ($ClassId, $LibVersion) = @_;
9635 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
9636 my $Shift = 0;
9637 foreach my $BaseId (@Bases)
9638 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009639 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009640 {
9641 if($Size!=1)
9642 { # not empty base class
9643 $Shift+=$Size;
9644 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009645 }
9646 }
9647 return $Shift;
9648}
9649
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009650sub getVTable_Size($$)
9651{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009652 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009653 my $Size = 0;
9654 # three approaches
9655 if(not $Size)
9656 { # real size
9657 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
9658 $Size = keys(%VTable);
9659 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009660 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009661 if(not $Size)
9662 { # shared library symbol size
9663 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
9664 $Size /= $WORD_SIZE{$LibVersion};
9665 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009666 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009667 if(not $Size)
9668 { # model size
9669 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
9670 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
9671 }
9672 }
9673 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009674}
9675
9676sub isCopyingClass($$)
9677{
9678 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009679 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009680}
9681
9682sub isLeafClass($$)
9683{
9684 my ($ClassId, $LibVersion) = @_;
9685 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
9686}
9687
9688sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009689{ # check structured type for public fields
9690 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009691}
9692
9693sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009694{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009695 my ($TypePtr, $Skip, $Start, $End) = @_;
9696 return 0 if(not $TypePtr);
9697 if($End==-1) {
9698 $End = keys(%{$TypePtr->{"Memb"}})-1;
9699 }
9700 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}}))
9701 {
9702 if($Skip and $Skip->{$MemPos})
9703 { # skip removed/added fields
9704 next;
9705 }
9706 if(int($MemPos)>=$Start and int($MemPos)<=$End)
9707 {
9708 if(isPublic($TypePtr, $MemPos)) {
9709 return ($MemPos+1);
9710 }
9711 }
9712 }
9713 return 0;
9714}
9715
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009716sub isReserved($)
9717{ # reserved fields == private
9718 my $MName = $_[0];
9719 if($MName=~/reserved|padding|f_spare/i) {
9720 return 1;
9721 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009722 if($MName=~/\A[_]*(spare|pad|unused)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009723 return 1;
9724 }
9725 if($MName=~/(pad\d+)/i) {
9726 return 1;
9727 }
9728 return 0;
9729}
9730
9731sub isPublic($$)
9732{
9733 my ($TypePtr, $FieldPos) = @_;
9734 return 0 if(not $TypePtr);
9735 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
9736 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
9737 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
9738 { # by name in C language
9739 # FIXME: add other methods to detect private members
9740 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
9741 if($MName=~/priv|abidata|parent_object/i)
9742 { # C-styled private data
9743 return 0;
9744 }
9745 if(lc($MName) eq "abi")
9746 { # ABI information/reserved field
9747 return 0;
9748 }
9749 if(isReserved($MName))
9750 { # reserved fields
9751 return 0;
9752 }
9753 return 1;
9754 }
9755 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
9756 { # by access in C++ language
9757 return 1;
9758 }
9759 return 0;
9760}
9761
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009762sub getVTable_Real($$)
9763{
9764 my ($ClassName, $LibVersion) = @_;
9765 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9766 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009767 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009768 if(defined $Type{"VTable"}) {
9769 return %{$Type{"VTable"}};
9770 }
9771 }
9772 return ();
9773}
9774
9775sub cmpVTables($)
9776{
9777 my $ClassName = $_[0];
9778 my $Res = cmpVTables_Real($ClassName, 1);
9779 if($Res==-1) {
9780 $Res = cmpVTables_Model($ClassName);
9781 }
9782 return $Res;
9783}
9784
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009785sub cmpVTables_Model($)
9786{
9787 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009788 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009789 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009790 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009791 return 1;
9792 }
9793 }
9794 return 0;
9795}
9796
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009797sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009798{
9799 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009800 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
9801 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009802 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009803 my %VTable_Old = getVTable_Real($ClassName, 1);
9804 my %VTable_New = getVTable_Real($ClassName, 2);
9805 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009806 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009807 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009808 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009809 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009810 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
9811 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009812 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009813 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009814 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009815 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009816 my $Entry1 = $VTable_Old{$Offset};
9817 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009818 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009819 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009820 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009821 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009822 $Entry1 = simpleVEntry($Entry1);
9823 $Entry2 = simpleVEntry($Entry2);
9824 if($Entry1 ne $Entry2)
9825 { # register as changed
9826 if($Entry1=~/::([^:]+)\Z/)
9827 {
9828 my $M1 = $1;
9829 if($Entry2=~/::([^:]+)\Z/)
9830 {
9831 my $M2 = $1;
9832 if($M1 eq $M2)
9833 { # overridden
9834 next;
9835 }
9836 }
9837 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009838 if(differentDumps("G"))
9839 {
9840 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
9841 {
9842 # GCC 4.6.1: -0x00000000000000010
9843 # GCC 4.7.0: -16
9844 next;
9845 }
9846 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009847 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009848 }
9849 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009850 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009851}
9852
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009853sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009854{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009855 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009856 foreach my $ClassName (keys(%{$VirtualTable{1}}))
9857 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009858 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009859 { # already registered
9860 next;
9861 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009862 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009863 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009864 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009865 foreach my $Symbol (@Affected)
9866 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009867 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009868 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009869 "Target"=>$ClassName);
9870 }
9871 }
9872 }
9873}
9874
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009875sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009876{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009877 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009878 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009879 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009880 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009881 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009882 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009883 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009884 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009885 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009886 if($TName_Tid{1}{$ClassName}
9887 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009888 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009889 if(defined $CompleteSignature{1}{$Symbol}
9890 and $CompleteSignature{1}{$Symbol}{"Virt"})
9891 { # override some method in v.1
9892 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009893 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009894 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009895 }
9896 }
9897 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009898 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009899 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009900 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009901 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009902 if($TName_Tid{2}{$ClassName}
9903 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009904 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009905 if(defined $CompleteSignature{2}{$Symbol}
9906 and $CompleteSignature{2}{$Symbol}{"Virt"})
9907 { # override some method in v.2
9908 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009909 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009910 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009911 }
9912 }
9913 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009914 if($Level eq "Binary")
9915 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009916 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009917 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
9918 { # check replacements, including pure virtual methods
9919 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
9920 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009921 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009922 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
9923 if($AddedPos==$RemovedPos)
9924 {
9925 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
9926 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
9927 last; # other methods will be reported as "added" or "removed"
9928 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009929 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009930 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
9931 {
9932 if(lc($AddedVFunc) eq lc($RemovedVFunc))
9933 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009934 next;
9935 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009936 my $ProblemType = "Virtual_Replacement";
9937 my @Affected = ($RemovedVFunc);
9938 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
9939 { # pure methods
9940 if(not isUsedClass($ClassId, 1, $Level))
9941 { # not a parameter of some exported method
9942 next;
9943 }
9944 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009945
9946 # affected all methods (both virtual and non-virtual ones)
9947 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
9948 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009949 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009950 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009951 foreach my $AffectedInt (@Affected)
9952 {
9953 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
9954 { # affected exported methods only
9955 next;
9956 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009957 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
9958 next;
9959 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009960 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
9961 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009962 "Target"=>get_Signature($AddedVFunc, 2),
9963 "Old_Value"=>get_Signature($RemovedVFunc, 1));
9964 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009965 }
9966 }
9967 }
9968 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009969 if(not checkDump(1, "2.0")
9970 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009971 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009972 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009973 return;
9974 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009975 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009976 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009977 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009978 next if(not $ClassId_Old);
9979 if(not isCreatable($ClassId_Old, 1))
9980 { # skip classes without public constructors (including auto-generated)
9981 # example: class has only a private exported or private inline constructor
9982 next;
9983 }
9984 if($ClassName=~/>/)
9985 { # skip affected template instances
9986 next;
9987 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009988 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009989 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009990 if(not $ClassId_New) {
9991 next;
9992 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009993 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009994 if($Class_New{"Type"}!~/Class|Struct/)
9995 { # became typedef
9996 if($Level eq "Binary") {
9997 next;
9998 }
9999 if($Level eq "Source")
10000 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010001 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010002 if($Class_New{"Type"}!~/Class|Struct/) {
10003 next;
10004 }
10005 $ClassId_New = $Class_New{"Tid"};
10006 }
10007 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010008 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10009 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 +040010010
10011 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10012 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10013
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010014 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010015 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10016 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010017 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10018 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010019 my $Shift_Old = getShift($ClassId_Old, 1);
10020 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010021 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010022 my ($Added, $Removed) = (0, 0);
10023 my @StableBases_Old = ();
10024 foreach my $BaseId (@Bases_Old)
10025 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010026 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010027 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010028 push(@StableBases_Old, $BaseId);
10029 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010030 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010031 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010032 { # removed base
10033 # excluding namespace::SomeClass to SomeClass renaming
10034 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010035 if($Level eq "Binary")
10036 { # Binary-level
10037 if($Shift_Old ne $Shift_New)
10038 { # affected fields
10039 if(havePubFields(\%Class_Old)) {
10040 $ProblemKind .= "_And_Shift";
10041 }
10042 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10043 $ProblemKind .= "_And_Size";
10044 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010045 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010046 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10047 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010048 { # affected v-table
10049 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010050 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010051 }
10052 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010053 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010054 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10055 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010056 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10057 {
10058 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10059 if($ProblemKind=~/VTable/) {
10060 $VTableChanged_M{$SubName}=1;
10061 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010062 }
10063 }
10064 foreach my $Interface (@Affected)
10065 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010066 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10067 next;
10068 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010069 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010070 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010071 "Target"=>$BaseName,
10072 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10073 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10074 "Shift"=>abs($Shift_New-$Shift_Old) );
10075 }
10076 $Removed+=1;
10077 }
10078 }
10079 my @StableBases_New = ();
10080 foreach my $BaseId (@Bases_New)
10081 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010082 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010083 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010084 push(@StableBases_New, $BaseId);
10085 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010086 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010087 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010088 { # added base
10089 # excluding namespace::SomeClass to SomeClass renaming
10090 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010091 if($Level eq "Binary")
10092 { # Binary-level
10093 if($Shift_Old ne $Shift_New)
10094 { # affected fields
10095 if(havePubFields(\%Class_Old)) {
10096 $ProblemKind .= "_And_Shift";
10097 }
10098 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10099 $ProblemKind .= "_And_Size";
10100 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010101 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010102 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10103 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010104 { # affected v-table
10105 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010106 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010107 }
10108 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010109 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010110 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10111 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010112 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10113 {
10114 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10115 if($ProblemKind=~/VTable/) {
10116 $VTableChanged_M{$SubName}=1;
10117 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010118 }
10119 }
10120 foreach my $Interface (@Affected)
10121 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010122 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10123 next;
10124 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010125 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010126 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010127 "Target"=>$BaseName,
10128 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10129 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10130 "Shift"=>abs($Shift_New-$Shift_Old) );
10131 }
10132 $Added+=1;
10133 }
10134 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010135 if($Level eq "Binary")
10136 { # Binary-level
10137 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010138 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10139 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010140 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010141 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010142 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010143 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010144 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010145 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10146 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010147 if($NewPos!=$OldPos)
10148 { # changed position of the base class
10149 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010150 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010151 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10152 next;
10153 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010154 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10155 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010156 "Target"=>$BaseName,
10157 "Old_Value"=>$OldPos-1,
10158 "New_Value"=>$NewPos-1 );
10159 }
10160 }
10161 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10162 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10163 { # became non-virtual base
10164 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10165 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010166 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10167 next;
10168 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010169 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10170 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010171 "Target"=>$BaseName );
10172 }
10173 }
10174 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10175 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10176 { # became virtual base
10177 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10178 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010179 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10180 next;
10181 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010182 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10183 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010184 "Target"=>$BaseName );
10185 }
10186 }
10187 }
10188 }
10189 # detect size changes in base classes
10190 if($Shift_Old!=$Shift_New)
10191 { # size of allocable class
10192 foreach my $BaseId (@StableBases_Old)
10193 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010194 my %BaseType = get_Type($BaseId, 1);
10195 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010196 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010197 if($Size_Old ne $Size_New
10198 and $Size_Old and $Size_New)
10199 {
10200 my $ProblemType = "";
10201 if(isCopyingClass($BaseId, 1)) {
10202 $ProblemType = "Size_Of_Copying_Class";
10203 }
10204 elsif($AllocableClass{1}{$BaseType{"Name"}})
10205 {
10206 if($Size_New>$Size_Old)
10207 { # increased size
10208 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010209 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010210 else
10211 { # decreased size
10212 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10213 if(not havePubFields(\%Class_Old))
10214 { # affected class has no public members
10215 next;
10216 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010217 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010218 }
10219 next if(not $ProblemType);
10220 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10221 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010222 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10223 next;
10224 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010225 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10226 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010227 "Target"=>$BaseType{"Name"},
10228 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10229 "New_Size"=>$Size_New*$BYTE_SIZE );
10230 }
10231 }
10232 }
10233 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010234 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010235 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010236 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010237 { # compare virtual tables size in base classes
10238 my $VShift_Old = getVShift($ClassId_Old, 1);
10239 my $VShift_New = getVShift($ClassId_New, 2);
10240 if($VShift_Old ne $VShift_New)
10241 { # changes in the base class or changes in the list of base classes
10242 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10243 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10244 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010245 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010246 foreach my $BaseId (@AllBases_Old)
10247 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010248 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010249 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010250 { # lost base
10251 next;
10252 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010253 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10254 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010255 if($VSize_Old!=$VSize_New)
10256 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010257 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010258 { # TODO: affected non-virtual methods?
10259 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010260 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10261 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010262 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010263 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010264 { # skip interfaces that have not changed the absolute virtual position
10265 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010266 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010267 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10268 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010269 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010270 $VTableChanged_M{$BaseType{"Name"}} = 1;
10271 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010272 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10273 { # the reason of the layout change: added virtual functions
10274 next if($VirtualReplacement{$VirtFunc});
10275 my $ProblemType = "Added_Virtual_Method";
10276 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10277 $ProblemType = "Added_Pure_Virtual_Method";
10278 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010279 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010280 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010281 "Target"=>get_Signature($VirtFunc, 2) );
10282 }
10283 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
10284 { # the reason of the layout change: removed virtual functions
10285 next if($VirtualReplacement{$VirtFunc});
10286 my $ProblemType = "Removed_Virtual_Method";
10287 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
10288 $ProblemType = "Removed_Pure_Virtual_Method";
10289 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010290 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010291 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010292 "Target"=>get_Signature($VirtFunc, 1) );
10293 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010294 }
10295 }
10296 }
10297 }
10298 }
10299 }
10300 }
10301}
10302
10303sub isCreatable($$)
10304{
10305 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010306 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010307 or isCopyingClass($ClassId, $LibVersion)) {
10308 return 1;
10309 }
10310 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10311 { # Fix for incomplete data: if this class has
10312 # a base class then it should also has a constructor
10313 return 1;
10314 }
10315 if($ReturnedClass{$LibVersion}{$ClassId})
10316 { # returned by some method of this class
10317 # or any other class
10318 return 1;
10319 }
10320 return 0;
10321}
10322
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010323sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010324{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010325 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010326 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
10327 { # parameter of some exported method
10328 return 1;
10329 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010330 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
10331 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010332 { # method from target class
10333 return 1;
10334 }
10335 return 0;
10336}
10337
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010338sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010339{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010340 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010341 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010342 # - virtual
10343 # - pure-virtual
10344 # - non-virtual
10345 if($CompleteSignature{1}{$Interface}{"Data"})
10346 { # global data is not affected
10347 return;
10348 }
10349 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010350 if(not $Class_Id) {
10351 return;
10352 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010353 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010354 if(cmpVTables_Real($CName, 1)==0)
10355 { # no changes
10356 return;
10357 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010358 $CheckedTypes{$Level}{$CName} = 1;
10359 if($Level eq "Binary")
10360 { # Binary-level
10361 if($CompleteSignature{1}{$Interface}{"PureVirt"}
10362 and not isUsedClass($Class_Id, 1, $Level))
10363 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010364 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010365 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010366 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010367 }
10368 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
10369 {
10370 if(defined $VirtualTable{2}{$CName}{$Func}
10371 and defined $CompleteSignature{2}{$Func})
10372 {
10373 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
10374 and $CompleteSignature{2}{$Func}{"PureVirt"})
10375 { # became pure virtual
10376 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
10377 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010378 "Target"=>get_Signature_M($Func, 1) );
10379 $VTableChanged_M{$CName} = 1;
10380 }
10381 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
10382 and not $CompleteSignature{2}{$Func}{"PureVirt"})
10383 { # became non-pure virtual
10384 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
10385 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010386 "Target"=>get_Signature_M($Func, 1) );
10387 $VTableChanged_M{$CName} = 1;
10388 }
10389 }
10390 }
10391 if($Level eq "Binary")
10392 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010393 # check virtual table structure
10394 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
10395 {
10396 next if($Interface eq $AddedVFunc);
10397 next if($VirtualReplacement{$AddedVFunc});
10398 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
10399 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
10400 { # pure virtual methods affect all others (virtual and non-virtual)
10401 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010402 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010403 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010404 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010405 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010406 elsif(not defined $VirtualTable{1}{$CName}
10407 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010408 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010409 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010410 { # became polymorphous class, added v-table pointer
10411 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010412 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010413 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010414 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010415 }
10416 else
10417 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010418 my $VSize_Old = getVTable_Size($CName, 1);
10419 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010420 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010421 if(isCopyingClass($Class_Id, 1))
10422 { # class has no constructors and v-table will be copied by applications, this may affect all methods
10423 my $ProblemType = "Added_Virtual_Method";
10424 if(isLeafClass($Class_Id, 1)) {
10425 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
10426 }
10427 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10428 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010429 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010430 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010431 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010432 else
10433 {
10434 my $ProblemType = "Added_Virtual_Method";
10435 if(isLeafClass($Class_Id, 1)) {
10436 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
10437 }
10438 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10439 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010440 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010441 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010442 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010443 }
10444 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010445 elsif($CompleteSignature{1}{$Interface}{"Virt"}
10446 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010447 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010448 if(defined $VirtualTable{1}{$CName}
10449 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010450 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010451 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
10452 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010453
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010454 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010455 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010456 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
10457 foreach my $ASymbol (@Affected)
10458 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010459 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
10460 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010461 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010462 next;
10463 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010464 }
10465 $CheckedSymbols{$Level}{$ASymbol} = 1;
10466 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
10467 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010468 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010469 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010470 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010471 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010472 }
10473 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010474 else {
10475 # safe
10476 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010477 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010478 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
10479 {
10480 next if($VirtualReplacement{$RemovedVFunc});
10481 if($RemovedVFunc eq $Interface
10482 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10483 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010484 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010485 next;
10486 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010487 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010488 { # became non-polymorphous class, removed v-table pointer
10489 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
10490 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010491 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010492 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010493 }
10494 elsif($CompleteSignature{1}{$Interface}{"Virt"}
10495 or $CompleteSignature{1}{$Interface}{"PureVirt"})
10496 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010497 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010498 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010499 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
10500 next;
10501 }
10502 my $VPos_New = -1;
10503 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010504 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010505 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
10506 }
10507 else
10508 {
10509 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010510 next;
10511 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010512 }
10513 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
10514 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
10515 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
10516 {
10517 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
10518 foreach my $ASymbol (@Affected)
10519 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010520 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
10521 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010522 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010523 next;
10524 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010525 }
10526 my $ProblemType = "Removed_Virtual_Method";
10527 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
10528 $ProblemType = "Removed_Pure_Virtual_Method";
10529 }
10530 $CheckedSymbols{$Level}{$ASymbol} = 1;
10531 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
10532 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010533 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010534 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010535 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010536 }
10537 }
10538 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010539 }
10540 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010541 else
10542 { # Source-level
10543 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010544 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010545 next if($Interface eq $AddedVFunc);
10546 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010547 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010548 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
10549 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010550 "Target"=>get_Signature($AddedVFunc, 2) );
10551 }
10552 }
10553 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
10554 {
10555 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10556 {
10557 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
10558 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010559 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010560 }
10561 }
10562 }
10563}
10564
10565sub find_MemberPair_Pos_byName($$)
10566{
10567 my ($Member_Name, $Pair_Type) = @_;
10568 $Member_Name=~s/\A[_]+|[_]+\Z//g;
10569 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
10570 {
10571 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
10572 {
10573 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
10574 $Name=~s/\A[_]+|[_]+\Z//g;
10575 if($Name eq $Member_Name) {
10576 return $MemberPair_Pos;
10577 }
10578 }
10579 }
10580 return "lost";
10581}
10582
10583sub find_MemberPair_Pos_byVal($$)
10584{
10585 my ($Member_Value, $Pair_Type) = @_;
10586 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
10587 {
10588 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
10589 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
10590 return $MemberPair_Pos;
10591 }
10592 }
10593 return "lost";
10594}
10595
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010596my %Severity_Val=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010597 "High"=>3,
10598 "Medium"=>2,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010599 "Low"=>1,
10600 "Safe"=>-1
10601);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010602
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010603sub maxSeverity($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010604{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010605 my ($S1, $S2) = @_;
10606 if(cmpSeverities($S1, $S2)) {
10607 return $S1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010608 }
10609 else {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010610 return $S2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010611 }
10612}
10613
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010614sub cmpSeverities($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010615{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010616 my ($S1, $S2) = @_;
10617 if(not $S1) {
10618 return 0;
10619 }
10620 elsif(not $S2) {
10621 return 1;
10622 }
10623 return ($Severity_Val{$S1}>$Severity_Val{$S2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010624}
10625
10626sub getProblemSeverity($$)
10627{
10628 my ($Level, $Kind) = @_;
10629 return $CompatRules{$Level}{$Kind}{"Severity"};
10630}
10631
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010632sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010633{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010634 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010635 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010636 if( $_->{"T1"} eq $_[0]
10637 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010638 {
10639 return 1;
10640 }
10641 }
10642 return 0;
10643}
10644
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010645sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010646{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010647 my %IDs = (
10648 "T1" => $_[0],
10649 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010650 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010651 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010652}
10653
10654sub isRenamed($$$$$)
10655{
10656 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
10657 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
10658 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010659 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010660 if(not defined $Type2->{"Memb"}{$MemPos}) {
10661 return "";
10662 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010663 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010664 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010665
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010666 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
10667 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010668 if($MemberPair_Pos_Rev eq "lost")
10669 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010670 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
10671 { # base type match
10672 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010673 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010674 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
10675 { # exact type match
10676 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010677 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010678 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
10679 { # size match
10680 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010681 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010682 if(isReserved($Pair_Name))
10683 { # reserved fields
10684 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010685 }
10686 }
10687 return "";
10688}
10689
10690sub isLastElem($$)
10691{
10692 my ($Pos, $TypeRef) = @_;
10693 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
10694 if($Name=~/last|count|max|total/i)
10695 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
10696 return 1;
10697 }
10698 elsif($Name=~/END|NLIMITS\Z/)
10699 { # __RLIMIT_NLIMITS
10700 return 1;
10701 }
10702 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
10703 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
10704 { # NImageFormats, NColorRoles
10705 return 1;
10706 }
10707 return 0;
10708}
10709
10710sub nonComparable($$)
10711{
10712 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010713
10714 my $N1 = $T1->{"Name"};
10715 my $N2 = $T2->{"Name"};
10716
10717 $N1=~s/\A(struct|union|enum) //;
10718 $N2=~s/\A(struct|union|enum) //;
10719
10720 if($N1 ne $N2
10721 and not isAnon($N1)
10722 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010723 { # different names
10724 if($T1->{"Type"} ne "Pointer"
10725 or $T2->{"Type"} ne "Pointer")
10726 { # compare base types
10727 return 1;
10728 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010729 if($N1!~/\Avoid\s*\*/
10730 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010731 {
10732 return 1;
10733 }
10734 }
10735 elsif($T1->{"Type"} ne $T2->{"Type"})
10736 { # different types
10737 if($T1->{"Type"} eq "Class"
10738 and $T2->{"Type"} eq "Struct")
10739 { # "class" to "struct"
10740 return 0;
10741 }
10742 elsif($T2->{"Type"} eq "Class"
10743 and $T1->{"Type"} eq "Struct")
10744 { # "struct" to "class"
10745 return 0;
10746 }
10747 else
10748 { # "class" to "enum"
10749 # "union" to "class"
10750 # ...
10751 return 1;
10752 }
10753 }
10754 return 0;
10755}
10756
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010757sub isOpaque($)
10758{
10759 my $T = $_[0];
10760 if(not defined $T->{"Memb"})
10761 {
10762 return 1;
10763 }
10764 return 0;
10765}
10766
10767sub removeVPtr($)
10768{ # support for old ABI dumps
10769 my $TPtr = $_[0];
10770 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
10771 if($#Pos>=1)
10772 {
10773 foreach my $Pos (0 .. $#Pos-1)
10774 {
10775 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
10776 }
10777 delete($TPtr->{"Memb"}{$#Pos});
10778 }
10779}
10780
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010781sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010782{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010783 my ($Type1_Id, $Type2_Id, $Level) = @_;
10784 return () if(not $Type1_Id or not $Type2_Id);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010785 my (%Sub_SubProblems, %SubProblems) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010786 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010787 { # already merged
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010788 return %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010789 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010790 my %Type1 = get_Type($Type1_Id, 1);
10791 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010792 if(not $Type1{"Name"} or not $Type2{"Name"}) {
10793 return ();
10794 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010795
10796 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010797 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
10798 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010799 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
10800
10801 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
10802 {
10803 if($Type1_Pure{"Type"}=~/Struct|Union/
10804 and $Type2_Pure{"Type"}=~/Struct|Union/)
10805 {
10806 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
10807 {
10808 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
10809 "Target"=>$Type1_Pure{"Name"},
10810 "Type_Name"=>$Type1_Pure{"Name"} );
10811
10812 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
10813 return %SubProblems;
10814 }
10815 }
10816 }
10817
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010818 if(not $Type1_Pure{"Size"} or not $Type2_Pure{"Size"})
10819 { # including a case when "class Class { ... };" changed to "class Class;"
10820 return ();
10821 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010822 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010823 { # skip recursive declarations
10824 return ();
10825 }
10826 return () if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
10827 return () if($SkipTypes{1}{$Type1_Pure{"Name"}});
10828 return () if($SkipTypes{1}{$Type1{"Name"}});
10829
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010830 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
10831 { # support for old ABI dumps
10832 # _vptr field added in 3.0
10833 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
10834 {
10835 if(defined $Type2_Pure{"Memb"}
10836 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
10837 {
10838 if(keys(%{$Type2_Pure{"Memb"}})==1) {
10839 delete($Type2_Pure{"Memb"}{0});
10840 }
10841 else {
10842 removeVPtr(\%Type2_Pure);
10843 }
10844 }
10845 }
10846 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
10847 {
10848 if(defined $Type1_Pure{"Memb"}
10849 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
10850 {
10851 if(keys(%{$Type1_Pure{"Memb"}})==1) {
10852 delete($Type1_Pure{"Memb"}{0});
10853 }
10854 else {
10855 removeVPtr(\%Type1_Pure);
10856 }
10857 }
10858 }
10859 }
10860
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010861 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
10862 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010863
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010864 if(not $UseOldDumps and %Typedef_1 and %Typedef_2
10865 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
10866 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010867 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010868 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
10869 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010870 if($Base_1{"Name"} ne $Base_2{"Name"})
10871 {
10872 if(differentDumps("G")
10873 or differentDumps("V"))
10874 { # different GCC versions or different dumps
10875 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
10876 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
10877 # std::__va_list and __va_list
10878 $Base_1{"Name"}=~s/\A(\w+::)+//;
10879 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010880 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
10881 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010882 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010883 }
10884 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
10885 and $Base_1{"Name"} ne $Base_2{"Name"})
10886 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010887 if($Level eq "Binary"
10888 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010889 {
10890 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
10891 "Target"=>$Typedef_1{"Name"},
10892 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010893 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
10894 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
10895 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010896 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
10897 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010898 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010899 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010900 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
10901 {
10902 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
10903 "Target"=>$Typedef_1{"Name"},
10904 "Type_Name"=>$Typedef_1{"Name"},
10905 "Old_Value"=>$Base_1{"Name"},
10906 "New_Value"=>$Base_2{"Name"} );
10907 }
10908 else
10909 {
10910 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
10911 "Target"=>$Typedef_1{"Name"},
10912 "Type_Name"=>$Typedef_1{"Name"},
10913 "Old_Value"=>$Base_1{"Name"},
10914 "New_Value"=>$Base_2{"Name"} );
10915 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010916 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010917 }
10918 }
10919 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
10920 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010921 my $TT1 = $Type1_Pure{"Type"};
10922 my $TT2 = $Type2_Pure{"Type"};
10923
10924 if($TT1 ne $TT2
10925 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010926 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010927 my $Short1 = $Type1_Pure{"Name"};
10928 my $Short2 = $Type2_Pure{"Name"};
10929
10930 $Short1=~s/\A\Q$TT1\E //ig;
10931 $Short2=~s/\A\Q$TT2\E //ig;
10932
10933 if($Short1 eq $Short2)
10934 {
10935 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
10936 "Target"=>$Type1_Pure{"Name"},
10937 "Type_Name"=>$Type1_Pure{"Name"},
10938 "Old_Value"=>lc($Type1_Pure{"Type"}),
10939 "New_Value"=>lc($Type2_Pure{"Type"}) );
10940 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010941 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010942 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010943 return %SubProblems;
10944 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010945 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010946 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
10947 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
10948 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
10949 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010950 if($Level eq "Binary"
10951 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010952 {
10953 my $ProblemKind = "DataType_Size";
10954 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010955 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010956 {
10957 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
10958 $ProblemKind = "Size_Of_Copying_Class";
10959 }
10960 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
10961 {
10962 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
10963 $ProblemKind = "Size_Of_Allocable_Class_Increased";
10964 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010965 else
10966 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010967 # descreased size of allocable class
10968 # it has no special effects
10969 }
10970 }
10971 }
10972 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
10973 "Target"=>$Type1_Pure{"Name"},
10974 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010975 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
10976 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE,
10977 "InitialType_Type"=>$Type1_Pure{"Type"} );
10978 }
10979 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010980 if(defined $Type1_Pure{"BaseType"}
10981 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040010982 { # checking base types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010983 %Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010984 foreach my $Sub_SubProblemType (keys(%Sub_SubProblems))
10985 {
10986 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems{$Sub_SubProblemType}}))
10987 {
10988 foreach my $Attr (keys(%{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}})) {
10989 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr} = $Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr};
10990 }
10991 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{"InitialType_Type"} = $Type1_Pure{"Type"};
10992 }
10993 }
10994 }
10995 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
10996 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
10997 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
10998 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
10999 { # detect removed and renamed fields
11000 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11001 next if(not $Member_Name);
11002 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);
11003 if($MemberPair_Pos eq "lost")
11004 {
11005 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11006 {
11007 if(isUnnamed($Member_Name))
11008 { # support for old-version dumps
11009 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011010 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011011 next;
11012 }
11013 }
11014 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11015 { # renamed
11016 $RenamedField{$Member_Pos}=$RenamedTo;
11017 $RenamedField_Rev{$NameToPosB{$RenamedTo}}=$Member_Name;
11018 }
11019 else
11020 { # removed
11021 $RemovedField{$Member_Pos}=1;
11022 }
11023 }
11024 elsif($Type1_Pure{"Type"} eq "Enum")
11025 {
11026 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11027 next if($Member_Value1 eq "");
11028 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11029 if($MemberPair_Pos ne "lost")
11030 { # renamed
11031 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11032 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11033 if($MemberPair_Pos_Rev eq "lost")
11034 {
11035 $RenamedField{$Member_Pos}=$RenamedTo;
11036 $RenamedField_Rev{$NameToPosB{$RenamedTo}}=$Member_Name;
11037 }
11038 else {
11039 $RemovedField{$Member_Pos}=1;
11040 }
11041 }
11042 else
11043 { # removed
11044 $RemovedField{$Member_Pos}=1;
11045 }
11046 }
11047 }
11048 else
11049 { # related
11050 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11051 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11052 }
11053 }
11054 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11055 { # detect added fields
11056 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11057 next if(not $Member_Name);
11058 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);
11059 if($MemberPair_Pos eq "lost")
11060 {
11061 if(isUnnamed($Member_Name))
11062 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011063 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011064 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011065 next;
11066 }
11067 }
11068 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11069 {
11070 if(not $RenamedField_Rev{$Member_Pos})
11071 { # added
11072 $AddedField{$Member_Pos}=1;
11073 }
11074 }
11075 }
11076 }
11077 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11078 { # detect moved fields
11079 my (%RelPos, %RelPosName, %AbsPos) = ();
11080 my $Pos = 0;
11081 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11082 { # relative positions in 1st version
11083 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11084 next if(not $Member_Name);
11085 if(not $RemovedField{$Member_Pos})
11086 { # old type without removed fields
11087 $RelPos{1}{$Member_Name}=$Pos;
11088 $RelPosName{1}{$Pos} = $Member_Name;
11089 $AbsPos{1}{$Pos++} = $Member_Pos;
11090 }
11091 }
11092 $Pos = 0;
11093 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11094 { # relative positions in 2nd version
11095 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11096 next if(not $Member_Name);
11097 if(not $AddedField{$Member_Pos})
11098 { # new type without added fields
11099 $RelPos{2}{$Member_Name}=$Pos;
11100 $RelPosName{2}{$Pos} = $Member_Name;
11101 $AbsPos{2}{$Pos++} = $Member_Pos;
11102 }
11103 }
11104 foreach my $Member_Name (keys(%{$RelPos{1}}))
11105 {
11106 my $RPos1 = $RelPos{1}{$Member_Name};
11107 my $AbsPos1 = $NameToPosA{$Member_Name};
11108 my $Member_Name2 = $Member_Name;
11109 if(my $RenamedTo = $RenamedField{$AbsPos1})
11110 { # renamed
11111 $Member_Name2 = $RenamedTo;
11112 }
11113 my $RPos2 = $RelPos{2}{$Member_Name2};
11114 if($RPos2 ne "" and $RPos1 ne $RPos2)
11115 { # different relative positions
11116 my $AbsPos2 = $NameToPosB{$Member_Name2};
11117 if($AbsPos1 ne $AbsPos2)
11118 { # different absolute positions
11119 my $ProblemType = "Moved_Field";
11120 if(not isPublic(\%Type1_Pure, $AbsPos1))
11121 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011122 if($Level eq "Source") {
11123 next;
11124 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011125 $ProblemType = "Moved_Private_Field";
11126 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011127 if($Level eq "Binary"
11128 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011129 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011130 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011131 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011132 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011133 if($MemSize1 ne $MemSize2) {
11134 $ProblemType .= "_And_Size";
11135 }
11136 }
11137 if($ProblemType eq "Moved_Private_Field") {
11138 next;
11139 }
11140 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11141 "Target"=>$Member_Name,
11142 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011143 "Old_Value"=>$RPos1,
11144 "New_Value"=>$RPos2 );
11145 }
11146 }
11147 }
11148 }
11149 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011150 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011151 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11152 next if(not $Member_Name);
11153 if(my $RenamedTo = $RenamedField{$Member_Pos})
11154 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011155 if(defined $Constants{2}{$Member_Name})
11156 {
11157 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11158 { # define OLD NEW
11159 next; # Safe
11160 }
11161 }
11162
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011163 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11164 {
11165 if(isPublic(\%Type1_Pure, $Member_Pos))
11166 {
11167 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11168 "Target"=>$Member_Name,
11169 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011170 "Old_Value"=>$Member_Name,
11171 "New_Value"=>$RenamedTo );
11172 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011173 elsif(isReserved($Member_Name))
11174 {
11175 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11176 "Target"=>$Member_Name,
11177 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011178 "Old_Value"=>$Member_Name,
11179 "New_Value"=>$RenamedTo );
11180 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011181 }
11182 elsif($Type1_Pure{"Type"} eq "Enum")
11183 {
11184 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11185 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11186 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011187 "Old_Value"=>$Member_Name,
11188 "New_Value"=>$RenamedTo );
11189 }
11190 }
11191 elsif($RemovedField{$Member_Pos})
11192 { # removed
11193 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11194 {
11195 my $ProblemType = "Removed_Field";
11196 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011197 or isUnnamed($Member_Name))
11198 {
11199 if($Level eq "Source") {
11200 next;
11201 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011202 $ProblemType = "Removed_Private_Field";
11203 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011204 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011205 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011206 {
11207 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11208 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011209 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 +040011210 { # changed offset
11211 $ProblemType .= "_And_Layout";
11212 }
11213 }
11214 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11215 { # affected size
11216 $ProblemType .= "_And_Size";
11217 }
11218 }
11219 if($ProblemType eq "Removed_Private_Field") {
11220 next;
11221 }
11222 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11223 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011224 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011225 }
11226 elsif($Type2_Pure{"Type"} eq "Union")
11227 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011228 if($Level eq "Binary"
11229 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011230 {
11231 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11232 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011233 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011234 }
11235 else
11236 {
11237 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11238 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011239 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011240 }
11241 }
11242 elsif($Type1_Pure{"Type"} eq "Enum")
11243 {
11244 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11245 "Target"=>$Member_Name,
11246 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011247 "Old_Value"=>$Member_Name );
11248 }
11249 }
11250 else
11251 { # changed
11252 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11253 if($Type1_Pure{"Type"} eq "Enum")
11254 {
11255 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11256 next if($Member_Value1 eq "");
11257 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11258 next if($Member_Value2 eq "");
11259 if($Member_Value1 ne $Member_Value2)
11260 {
11261 my $ProblemType = "Enum_Member_Value";
11262 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11263 $ProblemType = "Enum_Last_Member_Value";
11264 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011265 if($SkipConstants{1}{$Member_Name}) {
11266 $ProblemType = "Enum_Private_Member_Value";
11267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011268 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11269 "Target"=>$Member_Name,
11270 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011271 "Old_Value"=>$Member_Value1,
11272 "New_Value"=>$Member_Value2 );
11273 }
11274 }
11275 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11276 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011277 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
11278 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
11279
11280 if($Access1 ne "private"
11281 and $Access2 eq "private")
11282 {
11283 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
11284 "Target"=>$Member_Name,
11285 "Type_Name"=>$Type1_Pure{"Name"});
11286 }
11287 elsif($Access1 ne "protected"
11288 and $Access1 ne "private"
11289 and $Access2 eq "protected")
11290 {
11291 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
11292 "Target"=>$Member_Name,
11293 "Type_Name"=>$Type1_Pure{"Name"});
11294 }
11295
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011296 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
11297 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011298 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011299 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
11300 $SizeV1 = $BSize1;
11301 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011302 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011303 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
11304 $SizeV2 = $BSize2;
11305 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011306 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
11307 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011308 if($Level eq "Binary"
11309 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011310 {
11311 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
11312 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
11313 { # field size change (including anon-structures and unions)
11314 # - same types
11315 # - unnamed types
11316 # - bitfields
11317 my $ProblemType = "Field_Size";
11318 if(not isPublic(\%Type1_Pure, $Member_Pos)
11319 or isUnnamed($Member_Name))
11320 { # should not be accessed by applications, goes to "Low Severity"
11321 # example: "abidata" members in GStreamer types
11322 $ProblemType = "Private_".$ProblemType;
11323 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011324 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 +040011325 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011326 if($Type2_Pure{"Type"} ne "Union"
11327 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011328 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011329 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 +040011330 { # changed offset
11331 $ProblemType .= "_And_Layout";
11332 }
11333 }
11334 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11335 $ProblemType .= "_And_Type_Size";
11336 }
11337 }
11338 if($ProblemType eq "Private_Field_Size")
11339 { # private field size with no effect
11340 $ProblemType = "";
11341 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040011342 if($ProblemType eq "Field_Size")
11343 {
11344 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
11345 { # Low severity
11346 $ProblemType = "Struct_Field_Size_Increased";
11347 }
11348 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011349 if($ProblemType)
11350 { # register a problem
11351 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11352 "Target"=>$Member_Name,
11353 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011354 "Old_Size"=>$SizeV1,
11355 "New_Size"=>$SizeV2);
11356 }
11357 }
11358 }
11359 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
11360 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
11361 { # do NOT check bitfield type changes
11362 next;
11363 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011364 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011365 {
11366 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
11367 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
11368 {
11369 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
11370 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011371 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011372 }
11373 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
11374 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
11375 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011376 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011377 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011378 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011379 }
11380 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011381 %Sub_SubProblems = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011382 foreach my $ProblemType (keys(%Sub_SubProblems))
11383 {
11384 my $Old_Value = $Sub_SubProblems{$ProblemType}{"Old_Value"};
11385 my $New_Value = $Sub_SubProblems{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011386
11387 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011388 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011389 or $ProblemType eq "Field_Type_And_Size"
11390 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011391 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011392 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011393 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011394 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011395 %{$Sub_SubProblems{"Field_Became_Volatile"}} = %{$Sub_SubProblems{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011396 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011397 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
11398 %{$Sub_SubProblems{"Field_Became_Non_Volatile"}} = %{$Sub_SubProblems{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011399 }
11400 }
11401 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
11402 {
11403 if($RA==2) {
11404 %{$Sub_SubProblems{"Field_Added_Const"}} = %{$Sub_SubProblems{$ProblemType}};
11405 }
11406 else {
11407 %{$Sub_SubProblems{"Field_Became_Const"}} = %{$Sub_SubProblems{$ProblemType}};
11408 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011409 }
11410 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
11411 {
11412 if($RR==2) {
11413 %{$Sub_SubProblems{"Field_Removed_Const"}} = %{$Sub_SubProblems{$ProblemType}};
11414 }
11415 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011416 %{$Sub_SubProblems{"Field_Became_Non_Const"}} = %{$Sub_SubProblems{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011417 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011418 }
11419 }
11420 }
11421
11422 if($Level eq "Source")
11423 {
11424 foreach my $ProblemType (keys(%Sub_SubProblems))
11425 {
11426 my $Old_Value = $Sub_SubProblems{$ProblemType}{"Old_Value"};
11427 my $New_Value = $Sub_SubProblems{$ProblemType}{"New_Value"};
11428
11429 if($ProblemType eq "Field_Type")
11430 {
11431 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011432 delete($Sub_SubProblems{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011433 }
11434 }
11435 }
11436 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011437
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011438 foreach my $ProblemType (keys(%Sub_SubProblems))
11439 {
11440 my $ProblemType_Init = $ProblemType;
11441 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011442 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011443 if(not isPublic(\%Type1_Pure, $Member_Pos)
11444 or isUnnamed($Member_Name)) {
11445 $ProblemType = "Private_".$ProblemType;
11446 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011447 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 +040011448 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011449 if($Type2_Pure{"Type"} ne "Union"
11450 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011451 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011452 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 +040011453 { # changed offset
11454 $ProblemType .= "_And_Layout";
11455 }
11456 }
11457 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11458 $ProblemType .= "_And_Type_Size";
11459 }
11460 }
11461 }
11462 else
11463 {
11464 if(not isPublic(\%Type1_Pure, $Member_Pos)
11465 or isUnnamed($Member_Name)) {
11466 next;
11467 }
11468 }
11469 if($ProblemType eq "Private_Field_Type_And_Size")
11470 { # private field change with no effect
11471 next;
11472 }
11473 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11474 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011475 "Type_Name"=>$Type1_Pure{"Name"});
11476
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011477 foreach my $Attr (keys(%{$Sub_SubProblems{$ProblemType_Init}}))
11478 { # other properties
11479 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubProblems{$ProblemType_Init}{$Attr};
11480 }
11481 }
11482 if(not isPublic(\%Type1_Pure, $Member_Pos))
11483 { # do NOT check internal type changes
11484 next;
11485 }
11486 if($MemberType1_Id and $MemberType2_Id)
11487 {# checking member type changes (replace)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011488 %Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011489 foreach my $Sub_SubProblemType (keys(%Sub_SubProblems))
11490 {
11491 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems{$Sub_SubProblemType}}))
11492 {
11493 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
11494 $SubProblems{$Sub_SubProblemType}{$NewLocation}{"IsInTypeInternals"}=1;
11495 foreach my $Attr (keys(%{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}})) {
11496 $SubProblems{$Sub_SubProblemType}{$NewLocation}{$Attr} = $Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr};
11497 }
11498 if($Sub_SubLocation!~/\-\>/) {
11499 $SubProblems{$Sub_SubProblemType}{$NewLocation}{"Start_Type_Name"} = $MemberType1_Name;
11500 }
11501 }
11502 }
11503 }
11504 }
11505 }
11506 }
11507 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11508 { # checking added members, public and private
11509 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11510 next if(not $Member_Name);
11511 if($AddedField{$Member_Pos})
11512 { # added
11513 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11514 {
11515 my $ProblemType = "Added_Field";
11516 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011517 or isUnnamed($Member_Name))
11518 {
11519 if($Level eq "Source") {
11520 next;
11521 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011522 $ProblemType = "Added_Private_Field";
11523 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011524 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011525 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011526 {
11527 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
11528 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011529 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 +040011530 { # changed offset
11531 $ProblemType .= "_And_Layout";
11532 }
11533 }
11534 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
11535 $ProblemType .= "_And_Size";
11536 }
11537 }
11538 if($ProblemType eq "Added_Private_Field")
11539 { # skip added private fields
11540 next;
11541 }
11542 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11543 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011544 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011545 }
11546 elsif($Type2_Pure{"Type"} eq "Union")
11547 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011548 if($Level eq "Binary"
11549 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011550 {
11551 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
11552 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011553 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011554 }
11555 else
11556 {
11557 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
11558 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011559 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011560 }
11561 }
11562 elsif($Type2_Pure{"Type"} eq "Enum")
11563 {
11564 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
11565 next if($Member_Value eq "");
11566 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
11567 "Target"=>$Member_Name,
11568 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011569 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011570 }
11571 }
11572 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011573 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011574 pop(@RecurTypes);
11575 return %SubProblems;
11576}
11577
11578sub isUnnamed($) {
11579 return $_[0]=~/\Aunnamed\d+\Z/;
11580}
11581
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011582sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011583{
11584 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011585 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
11586 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
11587 $TypeName = uncover_typedefs($TypeName, $LibVersion);
11588 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011589 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011590 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011591 }
11592 return $TypeName;
11593}
11594
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011595sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011596{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011597 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011598 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011599 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
11600 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011601 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011602 return () if(not $TypeInfo{$LibVersion}{$TypeId});
11603 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011604 return () if(not $Type{"Type"});
11605 if($Type{"Type"} ne $Type_Type)
11606 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011607 return () if(not $Type{"BaseType"});
11608 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011609 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011610 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011611 return %Type;
11612}
11613
11614my %TypeSpecAttributes = (
11615 "Const" => 1,
11616 "Volatile" => 1,
11617 "ConstVolatile" => 1,
11618 "Restrict" => 1,
11619 "Typedef" => 1
11620);
11621
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011622sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011623{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011624 my ($TypeId, $Info) = @_;
11625 if(not $TypeId or not $Info
11626 or not $Info->{$TypeId}) {
11627 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011628 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011629 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
11630 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
11631 }
11632 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011633 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011634 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011635 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011636 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011637 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011638 return %Type;
11639}
11640
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011641sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011642{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011643 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011644 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011645 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
11646 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011647 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011648 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
11649 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011650 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
11651 my $PLevel = 0;
11652 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
11653 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011654 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011655 return $PLevel if(not $Type{"BaseType"});
11656 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
11657 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
11658 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011659}
11660
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011661sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011662{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011663 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011664 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011665 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
11666 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011667 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011668 return () if(not $TypeInfo{$LibVersion}{$TypeId});
11669 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011670 return %Type if(not $Type{"BaseType"});
11671 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011672 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011673 return %Type;
11674}
11675
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011676sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011677{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011678 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011679 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011680 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
11681 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011682 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011683 my $Qual = "";
11684 if($Type{"Type"} eq "Pointer") {
11685 $Qual .= "*";
11686 }
11687 elsif($Type{"Type"} eq "Ref") {
11688 $Qual .= "&";
11689 }
11690 elsif($Type{"Type"} eq "ConstVolatile") {
11691 $Qual .= "const volatile";
11692 }
11693 elsif($Type{"Type"} eq "Const"
11694 or $Type{"Type"} eq "Volatile"
11695 or $Type{"Type"} eq "Restrict") {
11696 $Qual .= lc($Type{"Type"});
11697 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011698 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011699 return $BQual.$Qual;
11700}
11701
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011702sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011703{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011704 my ($TypeId, $Info) = @_;
11705 if(not $TypeId or not $Info
11706 or not $Info->{$TypeId}) {
11707 return ();
11708 }
11709 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011710 return %Type if(not $Type{"BaseType"});
11711 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011712 {
11713 if($Info->{$BTid}) {
11714 return %{$Info->{$BTid}};
11715 }
11716 else { # something is going wrong
11717 return ();
11718 }
11719 }
11720 else {
11721 return %Type;
11722 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011723}
11724
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011725sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011726{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011727 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011728 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011729 return () if(not $TypeInfo{$LibVersion}{$TypeId});
11730 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011731}
11732
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040011733sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011734{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011735 my $Symbol = $_[0];
11736 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
11737}
11738
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011739sub isInLineInst($$$) {
11740 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
11741}
11742
11743sub isTemplateInstance($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011744{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011745 my ($Symbol, $SInfo, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011746 if($CheckObjectsOnly)
11747 {
11748 if($Symbol!~/\A(_Z|\?)/) {
11749 return 0;
11750 }
11751 if(my $Signature = $tr_name{$Symbol})
11752 {
11753 if(index($Signature,">")==-1) {
11754 return 0;
11755 }
11756 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
11757 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011758 if(index($ShortName,"<")!=-1
11759 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011760 return 1;
11761 }
11762 }
11763 }
11764 }
11765 else
11766 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011767 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011768 {
11769 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
11770 {
11771 if(index($ClassName,"<")!=-1) {
11772 return 1;
11773 }
11774 }
11775 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011776 if(my $ShortName = $SInfo->{"ShortName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011777 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011778 if(index($ShortName,"<")!=-1
11779 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011780 return 1;
11781 }
11782 }
11783 }
11784 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011785}
11786
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011787sub isTemplateSpec($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011788{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011789 my ($Symbol, $SInfo, $LibVersion) = @_;
11790 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011791 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011792 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011793 { # class specialization
11794 return 1;
11795 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011796 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011797 { # method specialization
11798 return 1;
11799 }
11800 }
11801 return 0;
11802}
11803
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011804sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011805{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011806 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040011807 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011808 { # non-public global data
11809 return 0;
11810 }
11811 if($CheckObjectsOnly) {
11812 return 0 if($Symbol=~/\A(_init|_fini)\Z/);
11813 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011814 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011815 { # support for old ABI dumps in --headers-only mode
11816 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
11817 {
11818 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
11819 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011820 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011821 if(not $PType or $PType eq "Unknown") {
11822 return 0;
11823 }
11824 }
11825 }
11826 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011827 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011828 {
11829 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011830 if($SkipSymbols{$LibVersion}{$Symbol})
11831 { # user defined symbols to ignore
11832 return 0;
11833 }
11834 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
11835 if(not $NameSpace and $ClassId)
11836 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011837 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011838 }
11839 if($NameSpace)
11840 { # user defined namespaces to ignore
11841 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
11842 return 0;
11843 }
11844 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
11845 { # nested namespaces
11846 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
11847 return 0;
11848 }
11849 }
11850 }
11851 if(my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
11852 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011853 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011854 { # --skip-headers or <skip_headers> (not <skip_including>)
11855 if($Skip==1) {
11856 return 0;
11857 }
11858 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011859 }
11860 if($SymbolsListPath and not $SymbolsList{$Symbol})
11861 { # user defined symbols
11862 return 0;
11863 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011864 if($SkipSymbolsListPath and $SkipSymbolsList{$Symbol})
11865 { # user defined symbols
11866 return 0;
11867 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011868 if($AppPath and not $SymbolsList_App{$Symbol})
11869 { # user defined symbols (in application)
11870 return 0;
11871 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011872 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
11873 { # non-target symbols
11874 return 0;
11875 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011876 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011877 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011878 if($CheckObjectsOnly)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011879 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011880 if(isTemplateInstance($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011881 return 0;
11882 }
11883 }
11884 else
11885 {
11886 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040011887 or isInLineInst($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011888 {
11889 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
11890 { # inline virtual methods
11891 if($Type=~/InlineVirt/) {
11892 return 1;
11893 }
11894 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
11895 if(not $Allocable)
11896 { # check bases
11897 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
11898 {
11899 if(not isCopyingClass($DCId, $LibVersion))
11900 { # exists a derived class without default c-tor
11901 $Allocable=1;
11902 last;
11903 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011904 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011905 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011906 if(not $Allocable) {
11907 return 0;
11908 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011909 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011910 else
11911 { # inline non-virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011912 return 0;
11913 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011914 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011915 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011916 }
11917 }
11918 return 1;
11919}
11920
11921sub mergeImpl()
11922{
11923 my $DiffCmd = get_CmdPath("diff");
11924 if(not $DiffCmd) {
11925 exitStatus("Not_Found", "can't find \"diff\"");
11926 }
11927 foreach my $Interface (sort keys(%{$Symbol_Library{1}}))
11928 { # implementation changes
11929 next if($CompleteSignature{1}{$Interface}{"Private"});
11930 next if(not $CompleteSignature{1}{$Interface}{"Header"} and not $CheckObjectsOnly);
11931 next if(not $Symbol_Library{2}{$Interface} and not $Symbol_Library{2}{$SymVer{2}{$Interface}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011932 if(not symbolFilter($Interface, 1, "Affected", "Binary")) {
11933 next;
11934 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011935 my $Impl1 = canonifyImpl($Interface_Impl{1}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011936 next if(not $Impl1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011937 my $Impl2 = canonifyImpl($Interface_Impl{2}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011938 next if(not $Impl2);
11939 if($Impl1 ne $Impl2)
11940 {
11941 writeFile("$TMP_DIR/impl1", $Impl1);
11942 writeFile("$TMP_DIR/impl2", $Impl2);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040011943 my $Diff = `$DiffCmd -rNau \"$TMP_DIR/impl1\" \"$TMP_DIR/impl2\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011944 $Diff=~s/(---|\+\+\+).+\n//g;
11945 $Diff=~s/[ ]{3,}/ /g;
11946 $Diff=~s/\n\@\@/\n \n\@\@/g;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040011947 unlink("$TMP_DIR/impl1");
11948 unlink("$TMP_DIR/impl2");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011949 %{$CompatProblems_Impl{$Interface}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011950 "Diff" => get_CodeView($Diff) );
11951 }
11952 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011953
11954 # clean memory
11955 %Interface_Impl = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011956}
11957
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011958sub canonifyImpl($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011959{
11960 my $FuncBody= $_[0];
11961 return "" if(not $FuncBody);
11962 $FuncBody=~s/0x[a-f\d]+/0x?/g;# addr
11963 $FuncBody=~s/((\A|\n)[a-z]+[\t ]+)[a-f\d]+([^x]|\Z)/$1?$3/g;# call, jump
11964 $FuncBody=~s/# [a-f\d]+ /# ? /g;# call, jump
11965 $FuncBody=~s/%([a-z]+[a-f\d]*)/\%reg/g;# registers
11966 while($FuncBody=~s/\nnop[ \t]*(\n|\Z)/$1/g){};# empty op
11967 $FuncBody=~s/<.+?\.cpp.+?>/<name.cpp>/g;
11968 $FuncBody=~s/(\A|\n)[a-f\d]+ </$1? </g;# 5e74 <_ZN...
11969 $FuncBody=~s/\.L\d+/.L/g;
11970 $FuncBody=~s/#(-?)\d+/#$1?/g;# r3, [r3, #120]
11971 $FuncBody=~s/[\n]{2,}/\n/g;
11972 return $FuncBody;
11973}
11974
11975sub get_CodeView($)
11976{
11977 my $Code = $_[0];
11978 my $View = "";
11979 foreach my $Line (split(/\n/, $Code))
11980 {
11981 if($Line=~s/\A(\+|-)/$1 /g)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011982 { # bold line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011983 $View .= "<tr><td><b>".htmlSpecChars($Line)."</b></td></tr>\n";
11984 }
11985 else {
11986 $View .= "<tr><td>".htmlSpecChars($Line)."</td></tr>\n";
11987 }
11988 }
11989 return "<table class='code_view'>$View</table>\n";
11990}
11991
11992sub getImplementations($$)
11993{
11994 my ($LibVersion, $Path) = @_;
11995 return if(not $LibVersion or not -e $Path);
11996 if($OSgroup eq "macos")
11997 {
11998 my $OtoolCmd = get_CmdPath("otool");
11999 if(not $OtoolCmd) {
12000 exitStatus("Not_Found", "can't find \"otool\"");
12001 }
12002 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012003 foreach my $Line (split(/\n/, `$OtoolCmd -tv \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012004 {
12005 if($Line=~/\A\s*_(\w+)\s*:/i) {
12006 $CurInterface = $1;
12007 }
12008 elsif($Line=~/\A\s*[\da-z]+\s+(.+?)\Z/i) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012009 $Interface_Impl{$LibVersion}{$CurInterface} .= $1."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012010 }
12011 }
12012 }
12013 else
12014 {
12015 my $ObjdumpCmd = get_CmdPath("objdump");
12016 if(not $ObjdumpCmd) {
12017 exitStatus("Not_Found", "can't find \"objdump\"");
12018 }
12019 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012020 foreach my $Line (split(/\n/, `$ObjdumpCmd -d \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012021 {
12022 if($Line=~/\A[\da-z]+\s+<(\w+)>/i) {
12023 $CurInterface = $1;
12024 }
12025 else
12026 { # x86: 51fa:(\t)89 e5 (\t)mov %esp,%ebp
12027 # arm: 5020:(\t)e24cb004(\t)sub(\t)fp, ip, #4(\t); 0x4
12028 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 +040012029 $Interface_Impl{$LibVersion}{$CurInterface} .= $2."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012030 }
12031 }
12032 }
12033 }
12034}
12035
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012036sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012037{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012038 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012039 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12040 {
12041 if(link_symbol($Symbol, 1, "+Deps"))
12042 { # linker can find a new symbol
12043 # in the old-version library
12044 # So, it's not a new symbol
12045 next;
12046 }
12047 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012048 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012049 next;
12050 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012051 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012052 }
12053}
12054
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012055sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012056{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012057 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012058 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12059 {
12060 if($CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012061 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012062 }
12063 if(link_symbol($Symbol, 2, "+Deps"))
12064 { # linker can find an old symbol
12065 # in the new-version library
12066 next;
12067 }
12068 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012069 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012070 next;
12071 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012072 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012073 }
12074}
12075
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012076sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012077{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012078 my $Level = $_[0];
12079 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012080 { # checking added symbols
12081 next if($CompleteSignature{2}{$Symbol}{"Private"});
12082 next if(not $CompleteSignature{2}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012083 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012084 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012085 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012086 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012087 { # checking removed symbols
12088 next if($CompleteSignature{1}{$Symbol}{"Private"});
12089 next if(not $CompleteSignature{1}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012090 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012091 { # skip v-tables for templates, that should not be imported by applications
12092 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012093 if(my $CName = $VTableClass{$Symbol})
12094 {
12095 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12096 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012097 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012098 next;
12099 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012100 }
12101 }
12102 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012103 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012104 }
12105 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12106 { # symbols for pure virtual methods cannot be called by clients
12107 next;
12108 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012109 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012110 }
12111}
12112
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012113sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012114{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012115 my ($LibVersion, $V) = @_;
12116 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12117 return $Cache{"checkDump"}{$LibVersion}{$V};
12118 }
12119 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012120}
12121
12122sub detectAdded_H($)
12123{
12124 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012125 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12126 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012127 if($Level eq "Source")
12128 { # remove symbol version
12129 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12130 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012131
12132 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12133 { # skip artificial constructors
12134 next;
12135 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012136 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012137 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12138 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012139 next;
12140 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012141 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012142 next;
12143 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012144 if(not defined $CompleteSignature{1}{$Symbol}
12145 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12146 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012147 if($UsedDump{2}{"SrcBin"})
12148 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012149 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012150 { # support for old and different (!) ABI dumps
12151 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12152 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012153 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012154 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012155 {
12156 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12157 {
12158 if($Lang eq "C")
12159 { # support for old ABI dumps: missed extern "C" functions
12160 next;
12161 }
12162 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012163 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012164 else
12165 {
12166 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012167 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012168 next;
12169 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012170 }
12171 }
12172 }
12173 }
12174 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012175 }
12176 }
12177}
12178
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012179sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012180{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012181 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012182 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12183 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012184 if($Level eq "Source")
12185 { # remove symbol version
12186 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12187 $Symbol=$SN;
12188 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012189 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12190 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012191 next;
12192 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012193 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012194 next;
12195 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012196 if(not defined $CompleteSignature{2}{$Symbol}
12197 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012198 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012199 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012200 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012201 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012202 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012203 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12204 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012205 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012206 if($CheckHeadersOnly)
12207 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012208 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12209 {
12210 if($Lang eq "C")
12211 { # support for old ABI dumps: missed extern "C" functions
12212 next;
12213 }
12214 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012215 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012216 else
12217 {
12218 if(not link_symbol($Symbol, 1, "-Deps"))
12219 { # skip removed inline symbols
12220 next;
12221 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012222 }
12223 }
12224 }
12225 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012226 if(not checkDump(1, "2.15"))
12227 {
12228 if($Symbol=~/_IT_E\Z/)
12229 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12230 next;
12231 }
12232 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012233 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12234 {
12235 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12236 {
12237 if(defined $Constants{2}{$Short})
12238 {
12239 my $Val = $Constants{2}{$Short}{"Value"};
12240 if(defined $Func_ShortName{2}{$Val})
12241 { # old name defined to new
12242 next;
12243 }
12244 }
12245 }
12246
12247 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012248 $RemovedInt{$Level}{$Symbol} = 1;
12249 if($Level eq "Source")
12250 { # search for a source-compatible equivalent
12251 setAlternative($Symbol, $Level);
12252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012253 }
12254 }
12255}
12256
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012257sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012258{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012259 my $Level = $_[0];
12260 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012261 { # checking added symbols
12262 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012263 next if($CompleteSignature{2}{$Symbol}{"Private"});
12264 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012265 if($Level eq "Binary")
12266 {
12267 if($CompleteSignature{2}{$Symbol}{"InLine"})
12268 {
12269 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12270 { # skip inline non-virtual functions
12271 next;
12272 }
12273 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012274 }
12275 else
12276 { # Source
12277 if($SourceAlternative_B{$Symbol}) {
12278 next;
12279 }
12280 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012281 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012282 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012283 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012284 { # checking removed symbols
12285 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012286 next if($CompleteSignature{1}{$Symbol}{"Private"});
12287 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012288 if($Level eq "Binary")
12289 {
12290 if($CompleteSignature{1}{$Symbol}{"InLine"})
12291 {
12292 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
12293 { # skip inline non-virtual functions
12294 next;
12295 }
12296 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012297 }
12298 else
12299 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012300 if(my $Alt = $SourceAlternative{$Symbol})
12301 {
12302 if(defined $CompleteSignature{1}{$Alt}
12303 and $CompleteSignature{1}{$Symbol}{"Const"})
12304 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012305 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012306 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012307 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012308 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012309 }
12310 else
12311 { # do NOT show removed symbol
12312 next;
12313 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012314 }
12315 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012316 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012317 }
12318}
12319
12320sub addParamNames($)
12321{
12322 my $LibraryVersion = $_[0];
12323 return if(not keys(%AddIntParams));
12324 my $SecondVersion = $LibraryVersion==1?2:1;
12325 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
12326 {
12327 next if(not keys(%{$AddIntParams{$Interface}}));
12328 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012329 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012330 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
12331 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012332 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012333 if(defined $CompleteSignature{$SecondVersion}{$Interface}
12334 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
12335 {
12336 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
12337 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12338 }
12339 }
12340 else {
12341 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
12342 }
12343 }
12344 }
12345 }
12346}
12347
12348sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012349{ # detect changed typedefs to show
12350 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012351 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
12352 {
12353 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012354 my $BName1 = $Typedef_BaseName{1}{$Typedef};
12355 if(not $BName1 or isAnon($BName1)) {
12356 next;
12357 }
12358 my $BName2 = $Typedef_BaseName{2}{$Typedef};
12359 if(not $BName2 or isAnon($BName2)) {
12360 next;
12361 }
12362 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012363 $ChangedTypedef{$Typedef} = 1;
12364 }
12365 }
12366}
12367
12368sub get_symbol_suffix($$)
12369{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012370 my ($Symbol, $Full) = @_;
12371 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040012372 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012373 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012374 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012375 if(not $Full) {
12376 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
12377 }
12378 return $Suffix;
12379}
12380
12381sub get_symbol_prefix($$)
12382{
12383 my ($Symbol, $LibVersion) = @_;
12384 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
12385 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12386 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012387 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012388 }
12389 return $ShortName;
12390}
12391
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012392sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012393{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012394 my $Symbol = $_[0];
12395 my $PSymbol = $Symbol;
12396 if(not defined $CompleteSignature{2}{$PSymbol}
12397 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
12398 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
12399 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012400 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012401 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012402 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012403 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012404 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
12405 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012406 {
12407 if(defined $CompleteSignature{2}{$PSymbol}
12408 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12409 {
12410 $SourceAlternative{$Symbol} = $PSymbol;
12411 $SourceAlternative_B{$PSymbol} = $Symbol;
12412 if(not defined $CompleteSignature{1}{$PSymbol}
12413 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12414 $SourceReplacement{$Symbol} = $PSymbol;
12415 }
12416 }
12417 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012418 }
12419 else
12420 {
12421 foreach my $Sp ("KV", "VK", "K", "V")
12422 {
12423 if($PSymbol=~s/\A_ZN$Sp/_ZN/
12424 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
12425 {
12426 if(defined $CompleteSignature{2}{$PSymbol}
12427 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
12428 {
12429 $SourceAlternative{$Symbol} = $PSymbol;
12430 $SourceAlternative_B{$PSymbol} = $Symbol;
12431 if(not defined $CompleteSignature{1}{$PSymbol}
12432 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
12433 $SourceReplacement{$Symbol} = $PSymbol;
12434 }
12435 }
12436 }
12437 $PSymbol = $Symbol;
12438 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012439 }
12440 }
12441 }
12442 return "";
12443}
12444
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012445sub getSymKind($$)
12446{
12447 my ($Symbol, $LibVersion) = @_;
12448 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
12449 {
12450 return "Global_Data";
12451 }
12452 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
12453 {
12454 return "Method";
12455 }
12456 return "Function";
12457}
12458
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040012459sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012460{
12461 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012462 my %SubProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012463
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012464 mergeBases($Level);
12465
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012466 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012467 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012468 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012469 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012470 next;
12471 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012472 if(defined $CompleteSignature{1}{$Symbol}
12473 and $CompleteSignature{1}{$Symbol}{"Header"})
12474 { # double-check added symbol
12475 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012476 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012477 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012478 next;
12479 }
12480 if($Symbol=~/\A(_Z|\?)/)
12481 { # C++
12482 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
12483 }
12484 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
12485 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012486 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
12487 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012488 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012489 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012490 {
12491 if($TName_Tid{1}{$AffectedClass_Name})
12492 { # class should exist in previous version
12493 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
12494 { # old v-table is NOT copied by old applications
12495 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
12496 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012497 "Target"=>get_Signature($Symbol, 2),
12498 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012499 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012500 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012501 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012502 }
12503 }
12504 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012505 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
12506 { # check all removed exported symbols
12507 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012508 next;
12509 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012510 if(defined $CompleteSignature{2}{$Symbol}
12511 and $CompleteSignature{2}{$Symbol}{"Header"})
12512 { # double-check removed symbol
12513 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012514 }
12515 if($CompleteSignature{1}{$Symbol}{"Private"})
12516 { # skip private methods
12517 next;
12518 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012519 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012520 next;
12521 }
12522 $CheckedSymbols{$Level}{$Symbol} = 1;
12523 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
12524 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012525 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
12526 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012527 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012528 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
12529 {
12530 if($TName_Tid{2}{$AffectedClass_Name})
12531 { # class should exist in newer version
12532 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
12533 { # old v-table is NOT copied by old applications
12534 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
12535 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012536 "Target"=>get_Signature($OverriddenMethod, 1),
12537 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012538 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012539 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012540 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012541 }
12542 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012543 if($Level eq "Binary"
12544 and $OSgroup eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012545 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012546 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012547 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012548 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012549 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012550 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012551 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012552 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012553 {
12554 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
12555 "Target"=>$tr_name{$Symbol},
12556 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012557 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012558 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012559 else
12560 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012561 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012562 "Target"=>$tr_name{$Symbol},
12563 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012564 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012565 }
12566 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012567 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012568 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012569 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012570 {
12571 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
12572 "Target"=>$tr_name{$Symbol},
12573 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012574 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012575 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012576 else
12577 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012578 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012579 "Target"=>$tr_name{$Symbol},
12580 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012581 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012582 }
12583 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012584 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
12585 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
12586 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
12587 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
12588 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012589 {
12590 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012591 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012592 $ProblemType = "Global_Data_Symbol_Changed_Type";
12593 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012594 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
12595 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012596 "Old_Type"=>$RTName1,
12597 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012598 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012599 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012600 }
12601 }
12602 }
12603 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012604 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012605 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012606 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012607 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012608 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012609 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012610 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012611 if($CompleteSignature{1}{$Symbol}{"Constructor"})
12612 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012613 if($Symbol=~/(C1E|C2E)/)
12614 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012615 my $CtorType = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012616 $NewSym=~s/(C1E|C2E)/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012617 }
12618 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012619 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
12620 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012621 if($Symbol=~/(D0E|D1E|D2E)/)
12622 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012623 my $DtorType = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012624 $NewSym=~s/(D0E|D1E|D2E)/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012625 }
12626 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012627 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012628 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012629 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012630 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012631 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012632 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012633 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012634 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012635 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
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 Ponomarenko1bdef342012-03-19 17:23:47 +040012641 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012642 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012643 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012644 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012645 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012646 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012647 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012648 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012649 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012650 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012651 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012652 { # "volatile" to non-"volatile"
12653
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012654 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012655 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012656 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012657 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012658 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012659 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012660 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012661 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012662 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012663 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012664 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012665 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012666 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012667 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012668 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012669 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012670 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012671 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
12672 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012673 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012674 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012675 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012676 }
12677 }
12678 }
12679 }
12680 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012681 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12682 { # checking symbols
12683 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12684 if($Level eq "Source")
12685 { # remove symbol version
12686 $Symbol=$SN;
12687 }
12688 else
12689 { # Binary
12690 if(not $SV)
12691 { # symbol without version
12692 if(my $VSym = $SymVer{1}{$Symbol})
12693 { # the symbol is linked with versioned symbol
12694 if($CompleteSignature{2}{$VSym}{"MnglName"})
12695 { # show report for symbol@ver only
12696 next;
12697 }
12698 elsif(not link_symbol($VSym, 2, "-Deps"))
12699 { # changed version: sym@v1 to sym@v2
12700 # do NOT show report for symbol
12701 next;
12702 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012703 }
12704 }
12705 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012706 my $PSymbol = $Symbol;
12707 if($Level eq "Source"
12708 and my $S = $SourceReplacement{$Symbol})
12709 { # take a source-compatible replacement function
12710 $PSymbol = $S;
12711 }
12712 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012713 { # private symbols
12714 next;
12715 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012716 if(not defined $CompleteSignature{1}{$Symbol}
12717 or not defined $CompleteSignature{2}{$PSymbol})
12718 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012719 next;
12720 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012721 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
12722 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
12723 { # no mangled name
12724 next;
12725 }
12726 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12727 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012728 { # without a header
12729 next;
12730 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012731
12732 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
12733 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
12734 { # became pure
12735 next;
12736 }
12737 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
12738 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
12739 { # became non-pure
12740 next;
12741 }
12742
12743 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
12744 { # exported, target, inline virtual and pure virtual
12745 next;
12746 }
12747 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
12748 { # exported, target, inline virtual and pure virtual
12749 next;
12750 }
12751
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012752 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012753 {
12754 if($CompleteSignature{1}{$Symbol}{"Data"}
12755 and $CompleteSignature{2}{$PSymbol}{"Data"})
12756 {
12757 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
12758 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
12759 if(defined $Value1)
12760 {
12761 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
12762 if(defined $Value2)
12763 {
12764 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
12765 if($Value1 ne $Value2)
12766 {
12767 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
12768 "Old_Value"=>$Value1,
12769 "New_Value"=>$Value2,
12770 "Target"=>get_Signature($Symbol, 1) );
12771 }
12772 }
12773 }
12774 }
12775 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012776
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012777 if($CompleteSignature{2}{$PSymbol}{"Private"})
12778 {
12779 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
12780 "Target"=>get_Signature_M($PSymbol, 2) );
12781 }
12782 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
12783 and $CompleteSignature{2}{$PSymbol}{"Protected"})
12784 {
12785 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
12786 "Target"=>get_Signature_M($PSymbol, 2) );
12787 }
12788 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
12789 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
12790 {
12791 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
12792 "Target"=>get_Signature_M($PSymbol, 2) );
12793 }
12794
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012795 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012796 mergeVirtualTables($Symbol, $Level);
12797
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012798 if($COMPILE_ERRORS)
12799 { # if some errors occurred at the compiling stage
12800 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012801 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012802 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012803 { # missed information about parameters in newer version
12804 next;
12805 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012806 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012807 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012808 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012809 next;
12810 }
12811 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012812 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012813 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012814 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012815 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
12816 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012817 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
12818 "Target"=>get_Signature($Symbol, 1)
12819 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012820 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012821 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012822 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
12823 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012824 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012825 "Target"=>get_Signature($Symbol, 1)
12826 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012827 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012828 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
12829 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012830 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012831 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012832 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012833 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
12834 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
12835 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012836 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012837 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012838 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
12839 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012840 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012841 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012842 my $ProblemType = "Virtual_Method_Position";
12843 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
12844 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012845 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012846 if(isUsedClass($Class_Id, 1, $Level))
12847 {
12848 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012849 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012850 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012851 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
12852 next;
12853 }
12854 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012855 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012856 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
12857 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012858 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012859 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012860 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012861 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012862 }
12863 }
12864 }
12865 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012866 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
12867 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012868 { # do NOT check type changes in pure virtuals
12869 next;
12870 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012871 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012872 if($Symbol=~/\A(_Z|\?)/
12873 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012874 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012875 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012876 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012877 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012878 }
12879 }
12880 else
12881 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012882 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012883 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012884 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012885 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
12886 last if($PType2_Name eq "...");
12887 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
12888 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012889 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012890 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012891 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012892 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
12893 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012894 if($#Positions1==-1 or $#Positions2>$#Positions1) {
12895 $ParamPos_Prev = "lost";
12896 }
12897 }
12898 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012899 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012900 }
12901 if($ParamPos_Prev eq "lost")
12902 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012903 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012904 {
12905 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012906 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012907 $ProblemType = "Added_Unnamed_Parameter";
12908 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012909 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012910 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012911 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012912 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012913 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012914 }
12915 else
12916 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012917 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012918 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012919 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012920 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
12921 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012922 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012923 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012924 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012925 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012926 "Target"=>$PName_Old,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012927 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012928 "Param_Type"=>$PType2_Name,
12929 "Old_Value"=>$PName_Old,
12930 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012931 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012932 }
12933 }
12934 else
12935 {
12936 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012937 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012938 $ProblemType = "Added_Middle_Unnamed_Parameter";
12939 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012940 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012941 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012942 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012943 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012944 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012945 }
12946 }
12947 }
12948 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012949 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012950 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012951 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012952 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012953 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012954 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012955 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012956 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012957 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012958 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
12959 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012960 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012961 }
12962 }
12963 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012964 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012965 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012966 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012967 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
12968 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012969 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
12970 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012971 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012972 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012973 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012974 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
12975 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012976 if($#Positions2==-1 or $#Positions2<$#Positions1) {
12977 $ParamPos_New = "lost";
12978 }
12979 }
12980 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012981 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012982 }
12983 if($ParamPos_New eq "lost")
12984 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012985 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012986 {
12987 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012988 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012989 $ProblemType = "Removed_Unnamed_Parameter";
12990 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012991 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040012992 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012993 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012994 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012995 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012996 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012997 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012998 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012999 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013000 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013001 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013002 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013003 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013004 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013005 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013006 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013007 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013008 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013009 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013010 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013011 "Old_Value"=>$PName,
13012 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013013 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013014 }
13015 }
13016 else
13017 {
13018 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013019 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013020 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13021 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013022 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013023 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013024 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013025 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013026 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013027 }
13028 }
13029 }
13030 }
13031 }
13032 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013033 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13034 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
13035 %SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013036
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013037 foreach my $SubProblemType (keys(%SubProblems))
13038 {
13039 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13040 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013041 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013042
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013043 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013044 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013045 if($SubProblemType eq "Return_Type_And_Size") {
13046 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13047 }
13048 elsif($SubProblemType eq "Return_Type_Format") {
13049 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13050 }
13051 else {
13052 $ProblemTypes{"Global_Data_Type"} = 1;
13053 }
13054
13055 # quals
13056 if($SubProblemType eq "Return_Type"
13057 or $SubProblemType eq "Return_Type_And_Size"
13058 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013059 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013060 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13061 { # const to non-const
13062 if($RR==2) {
13063 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13064 }
13065 else {
13066 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13067 }
13068 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013069 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013070 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13071 { # non-const to const
13072 if($RA==2) {
13073 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13074 }
13075 else {
13076 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13077 }
13078 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013079 }
13080 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013081 }
13082 else
13083 {
13084 # quals
13085 if($SubProblemType eq "Return_Type"
13086 or $SubProblemType eq "Return_Type_And_Size"
13087 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013088 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013089 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013090 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013091 if(addedQual($Old_Value, $New_Value, "volatile"))
13092 {
13093 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13094 if($Level ne "Source"
13095 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13096 $ProblemTypes{"Return_Type"} = 1;
13097 }
13098 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013099 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013100 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13101 {
13102 if($RA==2) {
13103 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13104 }
13105 else {
13106 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13107 }
13108 if($Level ne "Source"
13109 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13110 $ProblemTypes{"Return_Type"} = 1;
13111 }
13112 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013113 }
13114 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013115 if($Level eq "Binary"
13116 and not $CompleteSignature{1}{$Symbol}{"Data"})
13117 {
13118 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13119 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13120 { # if one of the architectures is unknown
13121 # then set other arhitecture to unknown too
13122 ($Arch1, $Arch2) = ("unknown", "unknown");
13123 }
13124 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013125 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013126 {
13127 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13128 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13129 }
13130 else
13131 {
13132 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13133 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13134 }
13135
13136 if($SubProblemType eq "Return_Type_Became_Void")
13137 {
13138 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13139 { # parameters stack has been affected
13140 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013141 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013142 }
13143 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013144 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013145 }
13146 }
13147 }
13148 elsif($SubProblemType eq "Return_Type_From_Void")
13149 {
13150 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13151 { # parameters stack has been affected
13152 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013153 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013154 }
13155 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013156 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013157 }
13158 }
13159 }
13160 elsif($SubProblemType eq "Return_Type"
13161 or $SubProblemType eq "Return_Type_And_Size"
13162 or $SubProblemType eq "Return_Type_Format")
13163 {
13164 if($Conv1{"Method"} ne $Conv2{"Method"})
13165 {
13166 if($Conv1{"Method"} eq "stack")
13167 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013168 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013169 }
13170 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013171 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013172 }
13173 }
13174 else
13175 {
13176 if($Conv1{"Method"} eq "reg")
13177 {
13178 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13179 {
13180 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013181 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013182 }
13183 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013184 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013185 }
13186 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013187 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013188 }
13189 }
13190 }
13191 }
13192 }
13193 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013194
13195 if(not keys(%ProblemTypes))
13196 { # default
13197 $ProblemTypes{$SubProblemType} = 1;
13198 }
13199
13200 foreach my $ProblemType (keys(%ProblemTypes))
13201 { # additional
13202 @{$CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013203 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013204 }
13205 if($ReturnType1_Id and $ReturnType2_Id)
13206 {
13207 @RecurTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013208 %SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013209
13210 if($CompleteSignature{1}{$Symbol}{"Data"})
13211 {
13212 if($Level eq "Binary")
13213 {
13214 if(get_PLevel($ReturnType1_Id, 1)==0)
13215 {
13216 foreach my $SubProblemType (keys(%SubProblems))
13217 { # add "Global_Data_Size" problem
13218 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13219 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
13220 if($SubProblemType eq "DataType_Size")
13221 { # add a new problem
13222 %{$SubProblems{"Global_Data_Size"}} = %{$SubProblems{$SubProblemType}};
13223 }
13224 }
13225 }
13226 if(not defined $SubProblems{"Global_Data_Size"})
13227 {
13228 if(defined $GlobalDataObject{1}{$Symbol}
13229 and defined $GlobalDataObject{2}{$Symbol})
13230 {
13231 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13232 my $New_Size = $GlobalDataObject{2}{$Symbol};
13233 if($Old_Size!=$New_Size)
13234 {
13235 %{$SubProblems{"Global_Data_Size"}{"retval"}} = (
13236 "Old_Size"=>$Old_Size*$BYTE_SIZE,
13237 "New_Size"=>$New_Size*$BYTE_SIZE );
13238 }
13239 }
13240 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013241 }
13242 }
13243 foreach my $SubProblemType (keys(%SubProblems))
13244 {
13245 foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}}))
13246 {
13247 my $NewLocation = ($SubLocation)?"retval->".$SubLocation:"retval";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013248 %{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013249 "Return_Type_Name"=>$TypeInfo{1}{$ReturnType1_Id}{"Name"} );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013250 @{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013251 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013252 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$ReturnType1_Id}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013253 }
13254 }
13255 }
13256 }
13257
13258 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013259 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13260 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13261 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013262 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013263 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013264 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13265 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013266 if($ThisPtr1_Id and $ThisPtr2_Id)
13267 {
13268 @RecurTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013269 %SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013270 foreach my $SubProblemType (keys(%SubProblems))
13271 {
13272 foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}}))
13273 {
13274 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013275 %{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013276 "Object_Type_Name"=>$TypeInfo{1}{$ObjTId1}{"Name"} );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013277 @{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013278 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013279 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$ObjTId1}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013280 }
13281 }
13282 }
13283 }
13284 }
13285 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013286 if($Level eq "Binary") {
13287 mergeVTables($Level);
13288 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013289 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
13290 $CheckedSymbols{$Level}{$Symbol} = 1;
13291 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013292}
13293
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013294sub rmQuals($$)
13295{
13296 my ($Value, $Qual) = @_;
13297 if(not $Qual) {
13298 return $Value;
13299 }
13300 if($Qual eq "all")
13301 { # all quals
13302 $Qual = "const|volatile|restrict";
13303 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013304 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013305 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013306 }
13307 return $Value;
13308}
13309
13310sub cmpBTypes($$$$)
13311{
13312 my ($T1, $T2, $V1, $V2) = @_;
13313 $T1 = uncover_typedefs($T1, $V1);
13314 $T2 = uncover_typedefs($T2, $V2);
13315 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
13316}
13317
13318sub addedQual($$$)
13319{
13320 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013321 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013322}
13323
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013324sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013325{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013326 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013327 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013328}
13329
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013330sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013331{
13332 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
13333 $Old_Value = uncover_typedefs($Old_Value, $V1);
13334 $New_Value = uncover_typedefs($New_Value, $V2);
13335 if($Old_Value eq $New_Value)
13336 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013337 return 0;
13338 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013339 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013340 { # without a qual
13341 return 0;
13342 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013343 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013344 { # became non-qual
13345 return 1;
13346 }
13347 else
13348 {
13349 my @BQ1 = getQualModel($Old_Value, $Qual);
13350 my @BQ2 = getQualModel($New_Value, $Qual);
13351 foreach (0 .. $#BQ1)
13352 { # removed qual
13353 if($BQ1[$_]==1
13354 and $BQ2[$_]!=1)
13355 {
13356 return 2;
13357 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013358 }
13359 }
13360 return 0;
13361}
13362
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013363sub getQualModel($$)
13364{
13365 my ($Value, $Qual) = @_;
13366 if(not $Qual) {
13367 return $Value;
13368 }
13369
13370 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013371 while($Value=~/(\w+)/ and $1 ne $Qual) {
13372 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013373 }
13374 $Value=~s/[^\*\&\w]+//g;
13375
13376 # modeling
13377 # int*const*const == 011
13378 # int**const == 001
13379 my @Model = ();
13380 my @Elems = split(/[\*\&]/, $Value);
13381 if(not @Elems) {
13382 return (0);
13383 }
13384 foreach (@Elems)
13385 {
13386 if($_ eq $Qual) {
13387 push(@Model, 1);
13388 }
13389 else {
13390 push(@Model, 0);
13391 }
13392 }
13393
13394 return @Model;
13395}
13396
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013397my %StringTypes = map {$_=>1} (
13398 "char*",
13399 "char const*"
13400);
13401
13402my %CharTypes = map {$_=>1} (
13403 "char",
13404 "char const"
13405);
13406
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013407sub showVal($$$)
13408{
13409 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013410 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040013411 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040013412 if(substr($Value, 0, 2) eq "_Z")
13413 {
13414 if(my $Unmangled = $tr_name{$Value}) {
13415 return $Unmangled;
13416 }
13417 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013418 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013419 { # strings
13420 return "\"$Value\"";
13421 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013422 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013423 { # characters
13424 return "\'$Value\'";
13425 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040013426 if($Value eq "")
13427 { # other
13428 return "\'\'";
13429 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013430 return $Value;
13431}
13432
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013433sub getRegs($$$)
13434{
13435 my ($LibVersion, $Symbol, $Pos) = @_;
13436
13437 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
13438 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013439 my %Regs = ();
13440 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
13441 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013442 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013443 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
13444 }
13445 }
13446
13447 return join(", ", sort keys(%Regs));
13448 }
13449
13450 return undef;
13451}
13452
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013453sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013454{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013455 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013456 if(not $Symbol) {
13457 return;
13458 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013459 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
13460 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
13461 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
13462 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013463 if(not $PType1_Id
13464 or not $PType2_Id) {
13465 return;
13466 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013467
13468 if(index($Symbol, "_Z")==0)
13469 { # do not merge this
13470 if($PName1 eq "this" or $PName2 eq "this") {
13471 return;
13472 }
13473 }
13474
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013475 my %Type1 = get_Type($PType1_Id, 1);
13476 my %Type2 = get_Type($PType2_Id, 2);
13477 my %BaseType1 = get_BaseType($PType1_Id, 1);
13478 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013479 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013480
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013481 if($Level eq "Binary")
13482 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013483 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013484 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
13485 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
13486 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
13487 {
13488 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013489 "Target"=>$PName1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013490 "Param_Pos"=>$ParamPos1 );
13491 }
13492 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
13493 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
13494 {
13495 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013496 "Target"=>$PName1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013497 "Param_Pos"=>$ParamPos1 );
13498 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013499 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013500
13501 if(defined $UsedDump{1}{"DWARF"}
13502 and defined $UsedDump{2}{"DWARF"})
13503 {
13504 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
13505 {
13506 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
13507 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
13508 if($Old_Regs and $New_Regs)
13509 {
13510 if($Old_Regs ne $New_Regs)
13511 {
13512 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
13513 "Target"=>$PName1,
13514 "Param_Pos"=>$ParamPos1,
13515 "Old_Value"=>$Old_Regs,
13516 "New_Value"=>$New_Regs );
13517 }
13518 }
13519 elsif($Old_Regs and not $New_Regs)
13520 {
13521 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
13522 "Target"=>$PName1,
13523 "Param_Pos"=>$ParamPos1,
13524 "Old_Value"=>$Old_Regs );
13525 }
13526 elsif(not $Old_Regs and $New_Regs)
13527 {
13528 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
13529 "Target"=>$PName1,
13530 "Param_Pos"=>$ParamPos1,
13531 "New_Value"=>$New_Regs );
13532 }
13533 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
13534 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
13535 {
13536 if($Old_Offset ne $New_Offset)
13537 {
13538 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
13539 "Target"=>$PName1,
13540 "Param_Pos"=>$ParamPos1,
13541 "Old_Value"=>$Old_Offset,
13542 "New_Value"=>$New_Offset );
13543 }
13544 }
13545 }
13546 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013547 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013548 if(checkDump(1, "2.0") and checkDump(2, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013549 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013550 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
13551 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013552 if(not checkDump(1, "2.13")
13553 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013554 { # support for old ABI dumps
13555 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013556 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013557 if($Type1{"Name"} eq "bool"
13558 and $Value_Old eq "false" and $Value_New eq "0")
13559 { # int class::method ( bool p = 0 );
13560 # old ABI dumps: "false"
13561 # new ABI dumps: "0"
13562 $Value_Old = "0";
13563 }
13564 }
13565 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040013566 if(not checkDump(1, "2.18")
13567 and checkDump(2, "2.18"))
13568 { # support for old ABI dumps
13569 if(not defined $Value_Old
13570 and substr($Value_New, 0, 2) eq "_Z") {
13571 $Value_Old = $Value_New;
13572 }
13573 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013574 if(defined $Value_Old)
13575 {
13576 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
13577 if(defined $Value_New)
13578 {
13579 $Value_New = showVal($Value_New, $PType2_Id, 2);
13580 if($Value_Old ne $Value_New)
13581 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013582 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013583 "Target"=>$PName1,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013584 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013585 "Old_Value"=>$Value_Old,
13586 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013587 }
13588 }
13589 else
13590 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013591 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013592 "Target"=>$PName1,
13593 "Param_Pos"=>$ParamPos1,
13594 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013595 }
13596 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013597 elsif(defined $Value_New)
13598 {
13599 $Value_New = showVal($Value_New, $PType2_Id, 2);
13600 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
13601 "Target"=>$PName1,
13602 "Param_Pos"=>$ParamPos1,
13603 "New_Value"=>$Value_New );
13604 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013605 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013606
13607 if($ChkRnmd)
13608 {
13609 if($PName1 and $PName2 and $PName1 ne $PName2
13610 and $PType1_Id!=-1 and $PType2_Id!=-1
13611 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
13612 { # except unnamed "..." value list (Id=-1)
13613 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
13614 "Target"=>$PName1,
13615 "Param_Pos"=>$ParamPos1,
13616 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
13617 "Old_Value"=>$PName1,
13618 "New_Value"=>$PName2,
13619 "New_Signature"=>get_Signature($Symbol, 2) );
13620 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013621 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013622
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013623 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013624 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013625 foreach my $SubProblemType (keys(%SubProblems))
13626 { # add new problems, remove false alarms
13627 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13628 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013629
13630 # quals
13631 if($SubProblemType eq "Parameter_Type"
13632 or $SubProblemType eq "Parameter_Type_And_Size"
13633 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013634 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013635 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013636 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013637 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013638 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013639 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013640 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
13641 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
13642 }
13643 }
13644 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
13645 {
13646 if(removedQual($Old_Value, $New_Value, "volatile")) {
13647 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013648 }
13649 }
13650 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
13651 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
13652 { # int to "int const"
13653 delete($SubProblems{$SubProblemType});
13654 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013655 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013656 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
13657 { # "int const" to int
13658 delete($SubProblems{$SubProblemType});
13659 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013660 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
13661 { # "const" to non-"const"
13662 if($RR==2) {
13663 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
13664 }
13665 else {
13666 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
13667 }
13668 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013669 }
13670 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013671
13672 if($Level eq "Source")
13673 {
13674 foreach my $SubProblemType (keys(%SubProblems))
13675 {
13676 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13677 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
13678
13679 if($SubProblemType eq "Parameter_Type")
13680 {
13681 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13682 delete($SubProblems{$SubProblemType});
13683 }
13684 }
13685 }
13686 }
13687
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013688 foreach my $SubProblemType (keys(%SubProblems))
13689 { # modify/register problems
13690 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13691 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013692 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
13693 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013694
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013695 my $NewProblemType = $SubProblemType;
13696 if($Old_Value eq "..." and $New_Value ne "...")
13697 { # change from "..." to "int"
13698 if($ParamPos1==0)
13699 { # ISO C requires a named argument before "..."
13700 next;
13701 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013702 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013703 }
13704 elsif($New_Value eq "..." and $Old_Value ne "...")
13705 { # change from "int" to "..."
13706 if($ParamPos2==0)
13707 { # ISO C requires a named argument before "..."
13708 next;
13709 }
13710 $NewProblemType = "Parameter_Became_VaList";
13711 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013712 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013713 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013714 {
13715 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013716 if($Arch1 eq "unknown"
13717 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013718 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013719 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013720 ($Arch1, $Arch2) = ("unknown", "unknown");
13721 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013722 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013723 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013724 { # real
13725 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
13726 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
13727 }
13728 else
13729 { # model
13730 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13731 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13732 }
13733 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013734 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013735 if($Conv1{"Method"} eq "stack")
13736 {
13737 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
13738 $NewProblemType = "Parameter_Type_And_Stack";
13739 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013740 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013741 elsif($Conv1{"Method"} eq "reg")
13742 {
13743 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
13744 $NewProblemType = "Parameter_Type_And_Register";
13745 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013746 }
13747 }
13748 else
13749 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013750 if($Conv1{"Method"} eq "stack") {
13751 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013752 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013753 elsif($Conv1{"Method"} eq "register") {
13754 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013755 }
13756 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013757 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
13758 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013759 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013760 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013761 "Target"=>$PName1,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013762 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013763 "New_Signature"=>get_Signature($Symbol, 2) );
13764 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013765 }
13766 @RecurTypes = ();
13767 # checking type definition changes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013768 my %SubProblems_Merge = mergeTypes($PType1_Id, $PType2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013769 foreach my $SubProblemType (keys(%SubProblems_Merge))
13770 {
13771 foreach my $SubLocation (keys(%{$SubProblems_Merge{$SubProblemType}}))
13772 {
13773 my $NewProblemType = $SubProblemType;
13774 if($SubProblemType eq "DataType_Size")
13775 {
13776 my $InitialType_Type = $SubProblems_Merge{$SubProblemType}{$SubLocation}{"InitialType_Type"};
13777 if($InitialType_Type!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
13778 { # stack has been affected
13779 $NewProblemType = "DataType_Size_And_Stack";
13780 }
13781 }
13782 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013783 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013784 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013785 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013786 "Param_Name"=>$PName1 );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013787 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}}{keys(%{$SubProblems_Merge{$SubProblemType}{$SubLocation}})} = values %{$SubProblems_Merge{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013788 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013789 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$PType1_Id}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013790 }
13791 }
13792 }
13793}
13794
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013795sub find_ParamPair_Pos_byName($$$)
13796{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013797 my ($Name, $Symbol, $LibVersion) = @_;
13798 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013799 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013800 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
13801 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013802 {
13803 return $ParamPos;
13804 }
13805 }
13806 return "lost";
13807}
13808
13809sub find_ParamPair_Pos_byTypeAndPos($$$$$)
13810{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013811 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013812 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013813 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013814 {
13815 next if($Order eq "backward" and $ParamPos>$MediumPos);
13816 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013817 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
13818 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013819 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013820 push(@Positions, $ParamPos);
13821 }
13822 }
13823 return @Positions;
13824}
13825
13826sub getTypeIdByName($$)
13827{
13828 my ($TypeName, $Version) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013829 return $TName_Tid{$Version}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013830}
13831
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013832sub diffTypes($$$)
13833{
13834 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
13835 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
13836 }
13837 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
13838 { # skip recursive declarations
13839 return 0;
13840 }
13841
13842 pushType($_[0], $_[1], \@RecurTypes_Diff);
13843 my $Diff = diffTypes_I(@_);
13844 pop(@RecurTypes_Diff);
13845
13846 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
13847}
13848
13849sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013850{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013851 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013852
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013853 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
13854 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013855
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013856 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
13857 { # equal types
13858 return 0;
13859 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013860 if($Type1_Pure{"Name"} eq "void")
13861 { # from void* to something
13862 return 0;
13863 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013864 if($Type1_Pure{"Name"}=~/\*/
13865 or $Type2_Pure{"Name"}=~/\*/)
13866 { # compared in detectTypeChange()
13867 return 0;
13868 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013869
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013870 my %FloatType = map {$_=>1} (
13871 "float",
13872 "double",
13873 "long double"
13874 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013875
13876 my $T1 = $Type1_Pure{"Type"};
13877 my $T2 = $Type2_Pure{"Type"};
13878
13879 if($T1 eq "Struct"
13880 and $T2 eq "Class")
13881 { # compare as data structures
13882 $T2 = "Struct";
13883 }
13884
13885 if($T1 eq "Class"
13886 and $T2 eq "Struct")
13887 { # compare as data structures
13888 $T1 = "Struct";
13889 }
13890
13891 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013892 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013893 if($T1 eq "Intrinsic"
13894 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013895 { # "int" to "enum"
13896 return 0;
13897 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013898 elsif($T2 eq "Intrinsic"
13899 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013900 { # "enum" to "int"
13901 return 0;
13902 }
13903 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013904 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013905 # ...
13906 return 1;
13907 }
13908 }
13909 else
13910 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013911 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013912 {
13913 if($FloatType{$Type1_Pure{"Name"}}
13914 or $FloatType{$Type2_Pure{"Name"}})
13915 { # "float" to "double"
13916 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013917 if($Level eq "Source")
13918 { # Safe
13919 return 0;
13920 }
13921 else {
13922 return 1;
13923 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013924 }
13925 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013926 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013927 {
13928 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
13929 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013930 if(not @Membs1
13931 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013932 { # private
13933 return 0;
13934 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013935 if($#Membs1!=$#Membs2)
13936 { # different number of elements
13937 return 1;
13938 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013939 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013940 {
13941 foreach my $Pos (@Membs1)
13942 { # compare elements by name and value
13943 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
13944 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
13945 { # different names
13946 return 1;
13947 }
13948 }
13949 }
13950 else
13951 {
13952 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013953 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013954 if($Level eq "Source")
13955 {
13956 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
13957 { # different names
13958 return 1;
13959 }
13960 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013961
13962 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
13963 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
13964
13965 if($MT1{"Name"} ne $MT2{"Name"}
13966 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
13967 {
13968 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
13969 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
13970
13971 if($PL1 ne $PL2)
13972 { # different pointer level
13973 return 1;
13974 }
13975
13976 # compare base types
13977 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
13978 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
13979
13980 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
13981 { # different types
13982 return 1;
13983 }
13984 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013985 }
13986 }
13987 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013988 else
13989 {
13990 # TODO: arrays, etc.
13991 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013992 }
13993 return 0;
13994}
13995
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013996sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013997{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013998 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013999 if(not $Type1_Id or not $Type2_Id) {
14000 return ();
14001 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014002 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014003 my %Type1 = get_Type($Type1_Id, 1);
14004 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014005 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14006 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14007 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14008 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 +040014009
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014010 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14011 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014012 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14013 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14014 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14015 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14016 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14017 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14018 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014019 if($Type1{"Name"} eq $Type2{"Name"})
14020 {
14021 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14022 { # will be reported in mergeTypes() as typedef problem
14023 return ();
14024 }
14025 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14026 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14027 if(%Typedef_1 and %Typedef_2)
14028 {
14029 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14030 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14031 { # const Typedef
14032 return ();
14033 }
14034 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014035 }
14036 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14037 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014038 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014039 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14040 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014041 {
14042 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14043 "Old_Value"=>$Type1_Base{"Name"},
14044 "New_Value"=>$Type2_Base{"Name"},
14045 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
14046 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
14047 "InitialType_Type"=>$Type1_Pure{"Type"});
14048 }
14049 else
14050 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014051 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014052 { # format change
14053 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14054 "Old_Value"=>$Type1_Base{"Name"},
14055 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014056 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
14057 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014058 "InitialType_Type"=>$Type1_Pure{"Type"});
14059 }
14060 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14061 {
14062 %{$LocalProblems{$Prefix."_BaseType"}}=(
14063 "Old_Value"=>$Type1_Base{"Name"},
14064 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014065 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
14066 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014067 "InitialType_Type"=>$Type1_Pure{"Type"});
14068 }
14069 }
14070 }
14071 }
14072 elsif($Type1{"Name"} ne $Type2{"Name"})
14073 { # type change
14074 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14075 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014076 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014077 and $Type1_Pure{"Name"} eq "void")
14078 {
14079 %{$LocalProblems{"Return_Type_From_Void"}}=(
14080 "New_Value"=>$Type2{"Name"},
14081 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
14082 "InitialType_Type"=>$Type1_Pure{"Type"});
14083 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014084 elsif($Prefix eq "Return"
14085 and $Type2_Pure{"Name"} eq "void")
14086 {
14087 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14088 "Old_Value"=>$Type1{"Name"},
14089 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14090 "InitialType_Type"=>$Type1_Pure{"Type"});
14091 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014092 else
14093 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014094 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014095 and $Type1{"Size"} and $Type2{"Size"}
14096 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014097 {
14098 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14099 "Old_Value"=>$Type1{"Name"},
14100 "New_Value"=>$Type2{"Name"},
14101 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14102 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
14103 "InitialType_Type"=>$Type1_Pure{"Type"});
14104 }
14105 else
14106 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014107 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014108 { # format change
14109 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14110 "Old_Value"=>$Type1{"Name"},
14111 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014112 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14113 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014114 "InitialType_Type"=>$Type1_Pure{"Type"});
14115 }
14116 elsif(tNameLock($Type1_Id, $Type2_Id))
14117 { # FIXME: correct this condition
14118 %{$LocalProblems{$Prefix."_Type"}}=(
14119 "Old_Value"=>$Type1{"Name"},
14120 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014121 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14122 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014123 "InitialType_Type"=>$Type1_Pure{"Type"});
14124 }
14125 }
14126 }
14127 }
14128 }
14129 if($Type1_PLevel!=$Type2_PLevel)
14130 {
14131 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14132 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14133 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014134 if($Level eq "Source")
14135 {
14136 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014137 "Old_Value"=>$Type1_PLevel,
14138 "New_Value"=>$Type2_PLevel);
14139 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014140 else
14141 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014142 if($Type2_PLevel>$Type1_PLevel)
14143 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014144 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14145 "Old_Value"=>$Type1_PLevel,
14146 "New_Value"=>$Type2_PLevel);
14147 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014148 else
14149 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014150 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14151 "Old_Value"=>$Type1_PLevel,
14152 "New_Value"=>$Type2_PLevel);
14153 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014154 }
14155 }
14156 }
14157 if($Type1_Pure{"Type"} eq "Array")
14158 { # base_type[N] -> base_type[N]
14159 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014160 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014161 foreach my $SubProblemType (keys(%SubProblems))
14162 {
14163 $SubProblemType=~s/_Type/_BaseType/g;
14164 next if(defined $LocalProblems{$SubProblemType});
14165 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14166 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14167 }
14168 }
14169 }
14170 return %LocalProblems;
14171}
14172
14173sub tNameLock($$)
14174{
14175 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014176 my $Changed = 0;
14177 if(differentDumps("G"))
14178 { # different GCC versions
14179 $Changed = 1;
14180 }
14181 elsif(differentDumps("V"))
14182 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014183 if(not checkDump(1, "2.20")
14184 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014185 { # latest names update
14186 # 2.6: added restrict qualifier
14187 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014188 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014189 $Changed = 1;
14190 }
14191 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014192
14193 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14194 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14195
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014196 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014197 { # different formats
14198 if($UseOldDumps)
14199 { # old dumps
14200 return 0;
14201 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014202
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014203 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14204 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014205
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014206 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014207 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014208 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014209 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014210 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014211 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014212 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014213 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014214 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14215 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14216 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014217 { # equal base types
14218 return 0;
14219 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014220
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014221 if(not checkDump(1, "2.13")
14222 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014223 { # broken array names in ABI dumps < 2.13
14224 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014225 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014226 return 0;
14227 }
14228 }
14229
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014230 if(not checkDump(1, "2.6")
14231 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014232 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014233 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014234 and $TN2=~/\brestrict\b/) {
14235 return 0;
14236 }
14237 }
14238
14239 if(not checkDump(1, "2.20")
14240 or not checkDump(2, "2.20"))
14241 { # added restrict attribute in 2.6
14242 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14243 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014244 return 0;
14245 }
14246 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014247 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014248 else
14249 {
14250 # typedef struct {...} type_t
14251 # typedef struct type_t {...} type_t
14252 if(index($TN1, " ".$TN2)!=-1)
14253 {
14254 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
14255 return 0;
14256 }
14257 }
14258 if(index($TN2, " ".$TN1)!=-1)
14259 {
14260 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
14261 return 0;
14262 }
14263 }
14264 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014265 return 1;
14266}
14267
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014268sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014269{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014270 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014271 if(defined $Cache{"differentDumps"}{$Check}) {
14272 return $Cache{"differentDumps"}{$Check};
14273 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014274 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014275 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014276 if($Check eq "G")
14277 {
14278 if(getGccVersion(1) ne getGccVersion(2))
14279 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014280 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014281 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014282 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014283 if($Check eq "V")
14284 {
14285 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
14286 formatVersion($UsedDump{2}{"V"}, 2))!=0)
14287 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014288 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014289 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014290 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014291 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014292 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014293}
14294
14295sub formatVersion($$)
14296{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014297 my ($V, $Digits) = @_;
14298 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014299 return join(".", splice(@Elems, 0, $Digits));
14300}
14301
14302sub htmlSpecChars($)
14303{
14304 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014305 if(not $Str) {
14306 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014307 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014308 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14309 $Str=~s/</&lt;/g;
14310 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
14311 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014312 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
14313 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014314 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014315 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014316 $Str=~s/\n/<br\/>/g;
14317 $Str=~s/\"/&quot;/g;
14318 $Str=~s/\'/&#39;/g;
14319 return $Str;
14320}
14321
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040014322sub xmlSpecChars($)
14323{
14324 my $Str = $_[0];
14325 if(not $Str) {
14326 return $Str;
14327 }
14328
14329 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
14330 $Str=~s/</&lt;/g;
14331 $Str=~s/>/&gt;/g;
14332
14333 $Str=~s/\"/&quot;/g;
14334 $Str=~s/\'/&#39;/g;
14335
14336 return $Str;
14337}
14338
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014339sub xmlSpecChars_R($)
14340{
14341 my $Str = $_[0];
14342 if(not $Str) {
14343 return $Str;
14344 }
14345
14346 $Str=~s/&amp;/&/g;
14347 $Str=~s/&lt;/</g;
14348 $Str=~s/&gt;/>/g;
14349
14350 $Str=~s/&quot;/"/g;
14351 $Str=~s/&#39;/'/g;
14352
14353 return $Str;
14354}
14355
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014356sub black_name($)
14357{
14358 my $Name = $_[0];
14359 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
14360}
14361
14362sub highLight_Signature($)
14363{
14364 my $Signature = $_[0];
14365 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
14366}
14367
14368sub highLight_Signature_Italic_Color($)
14369{
14370 my $Signature = $_[0];
14371 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
14372}
14373
14374sub separate_symbol($)
14375{
14376 my $Symbol = $_[0];
14377 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
14378 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
14379 ($Name, $Spec, $Ver) = ($1, $2, $3);
14380 }
14381 return ($Name, $Spec, $Ver);
14382}
14383
14384sub cut_f_attrs($)
14385{
14386 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
14387 return $2;
14388 }
14389 return "";
14390}
14391
14392sub highLight_Signature_PPos_Italic($$$$$)
14393{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014394 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
14395 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014396 if($CheckObjectsOnly) {
14397 $ItalicParams=$ColorParams=0;
14398 }
14399 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
14400 my $Return = "";
14401 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
14402 $Return = $2;
14403 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014404 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014405 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014406 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014407 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014408 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014409 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014410 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014411 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014412 }
14413 return $Signature;
14414 }
14415 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
14416 $Begin.=" " if($Begin!~/ \Z/);
14417 $End = cut_f_attrs($Signature);
14418 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014419 my ($Short, $Params) = split_Signature($Signature);
14420 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014421 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014422 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014423 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014424 $Part=~s/\A\s+|\s+\Z//g;
14425 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
14426 if($Part=~/\([\*]+(\w+)\)/i) {
14427 $ParamName = $1;#func-ptr
14428 }
14429 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
14430 $ParamName = $1;
14431 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014432 if(not $ParamName)
14433 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014434 push(@Parts, $Part_Styled);
14435 next;
14436 }
14437 if($ItalicParams and not $TName_Tid{1}{$Part}
14438 and not $TName_Tid{2}{$Part})
14439 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014440 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014441 if($Param_Pos ne ""
14442 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014443 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014444 }
14445 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014446 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014447 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014448 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014449 }
14450 $Part_Styled=~s/,(\w)/, $1/g;
14451 push(@Parts, $Part_Styled);
14452 }
14453 if(@Parts)
14454 {
14455 foreach my $Num (0 .. $#Parts)
14456 {
14457 if($Num==$#Parts)
14458 { # add ")" to the last parameter
14459 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
14460 }
14461 elsif(length($Parts[$Num])<=45) {
14462 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
14463 }
14464 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014465 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014466 }
14467 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014468 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014469 }
14470 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014471 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014472 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014473 $Signature=~s!\[\]![&#160;]!g;
14474 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014475 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
14476 if($SymbolVersion) {
14477 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
14478 }
14479 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014480}
14481
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014482sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014483{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014484 my $Signature = $_[0];
14485 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
14486 {
14487 $Signature=~s/\A\Q$ShortName\E\(//g;
14488 cut_f_attrs($Signature);
14489 $Signature=~s/\)\Z//;
14490 return ($ShortName, $Signature);
14491 }
14492
14493 # error
14494 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014495}
14496
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014497sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014498{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014499 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014500 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014501 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
14502 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014503 foreach my $Pos (0 .. length($Params) - 1)
14504 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014505 my $S = substr($Params, $Pos, 1);
14506 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014507 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014508 }
14509 if($S eq "," and
14510 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014511 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014512 if($Comma)
14513 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014514 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014515 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014516 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014517 }
14518 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014519 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014520 }
14521 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040014522 if(not $Sp)
14523 { # remove spaces
14524 foreach (@Parts)
14525 {
14526 s/\A //g;
14527 s/ \Z//g;
14528 }
14529 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014530 return @Parts;
14531}
14532
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014533sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014534{
14535 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014536 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014537 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014538 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
14539 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014540 $Center+=length($1);
14541 }
14542 foreach my $Pos (0 .. length($Sign)-1)
14543 {
14544 my $S = substr($Sign, $Pos, 1);
14545 if($S eq $Target)
14546 {
14547 if($B{"("}==$B{")"}
14548 and $B{"<"}==$B{">"}) {
14549 return $Center;
14550 }
14551 }
14552 if(defined $B{$S}) {
14553 $B{$S}+=1;
14554 }
14555 $Center+=1;
14556 }
14557 return 0;
14558}
14559
14560sub appendFile($$)
14561{
14562 my ($Path, $Content) = @_;
14563 return if(not $Path);
14564 if(my $Dir = get_dirname($Path)) {
14565 mkpath($Dir);
14566 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014567 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014568 print FILE $Content;
14569 close(FILE);
14570}
14571
14572sub writeFile($$)
14573{
14574 my ($Path, $Content) = @_;
14575 return if(not $Path);
14576 if(my $Dir = get_dirname($Path)) {
14577 mkpath($Dir);
14578 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014579 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014580 print FILE $Content;
14581 close(FILE);
14582}
14583
14584sub readFile($)
14585{
14586 my $Path = $_[0];
14587 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014588 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014589 local $/ = undef;
14590 my $Content = <FILE>;
14591 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014592 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014593 $Content=~s/\r/\n/g;
14594 }
14595 return $Content;
14596}
14597
14598sub get_filename($)
14599{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014600 if(defined $Cache{"get_filename"}{$_[0]}) {
14601 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014602 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014603 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
14604 return ($Cache{"get_filename"}{$_[0]}=$1);
14605 }
14606 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014607}
14608
14609sub get_dirname($)
14610{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014611 if(defined $Cache{"get_dirname"}{$_[0]}) {
14612 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014613 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014614 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
14615 return ($Cache{"get_dirname"}{$_[0]}=$1);
14616 }
14617 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014618}
14619
14620sub separate_path($) {
14621 return (get_dirname($_[0]), get_filename($_[0]));
14622}
14623
14624sub esc($)
14625{
14626 my $Str = $_[0];
14627 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
14628 return $Str;
14629}
14630
14631sub readLineNum($$)
14632{
14633 my ($Path, $Num) = @_;
14634 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040014635 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014636 foreach (1 ... $Num) {
14637 <FILE>;
14638 }
14639 my $Line = <FILE>;
14640 close(FILE);
14641 return $Line;
14642}
14643
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014644sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014645{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014646 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014647 return () if(not $Path or not -f $Path);
14648 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014649 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
14650 {
14651 foreach my $AttrVal (split(/;/, $1))
14652 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014653 if($AttrVal=~/(.+):(.+)/)
14654 {
14655 my ($Name, $Value) = ($1, $2);
14656 $Attributes{$Name} = $Value;
14657 }
14658 }
14659 }
14660 return \%Attributes;
14661}
14662
14663sub is_abs($) {
14664 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
14665}
14666
14667sub get_abs_path($)
14668{ # abs_path() should NOT be called for absolute inputs
14669 # because it can change them
14670 my $Path = $_[0];
14671 if(not is_abs($Path)) {
14672 $Path = abs_path($Path);
14673 }
14674 return $Path;
14675}
14676
14677sub get_OSgroup()
14678{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014679 my $N = $Config{"osname"};
14680 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014681 return "macos";
14682 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014683 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014684 return "bsd";
14685 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014686 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014687 return "beos";
14688 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014689 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014690 return "symbian";
14691 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014692 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014693 return "windows";
14694 }
14695 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014696 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014697 }
14698}
14699
14700sub getGccVersion($)
14701{
14702 my $LibVersion = $_[0];
14703 if($GCC_VERSION{$LibVersion})
14704 { # dump version
14705 return $GCC_VERSION{$LibVersion};
14706 }
14707 elsif($UsedDump{$LibVersion}{"V"})
14708 { # old-version dumps
14709 return "unknown";
14710 }
14711 my $GccVersion = get_dumpversion($GCC_PATH); # host version
14712 if(not $GccVersion) {
14713 return "unknown";
14714 }
14715 return $GccVersion;
14716}
14717
14718sub showArch($)
14719{
14720 my $Arch = $_[0];
14721 if($Arch eq "arm"
14722 or $Arch eq "mips") {
14723 return uc($Arch);
14724 }
14725 return $Arch;
14726}
14727
14728sub getArch($)
14729{
14730 my $LibVersion = $_[0];
14731 if($CPU_ARCH{$LibVersion})
14732 { # dump version
14733 return $CPU_ARCH{$LibVersion};
14734 }
14735 elsif($UsedDump{$LibVersion}{"V"})
14736 { # old-version dumps
14737 return "unknown";
14738 }
14739 if(defined $Cache{"getArch"}{$LibVersion}) {
14740 return $Cache{"getArch"}{$LibVersion};
14741 }
14742 my $Arch = get_dumpmachine($GCC_PATH); # host version
14743 if(not $Arch) {
14744 return "unknown";
14745 }
14746 if($Arch=~/\A([\w]{3,})(-|\Z)/) {
14747 $Arch = $1;
14748 }
14749 $Arch = "x86" if($Arch=~/\Ai[3-7]86\Z/);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040014750 if($OSgroup eq "windows")
14751 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014752 $Arch = "x86" if($Arch=~/win32|mingw32/i);
14753 $Arch = "x86_64" if($Arch=~/win64|mingw64/i);
14754 }
14755 $Cache{"getArch"}{$LibVersion} = $Arch;
14756 return $Arch;
14757}
14758
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014759sub get_Report_Header($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014760{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014761 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014762 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014763 if(getArch(1) ne getArch(2)
14764 or getArch(1) eq "unknown"
14765 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014766 { # don't show architecture in the header
14767 $ArchInfo="";
14768 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014769 my $Report_Header = "<h1><span class='nowrap'>";
14770 if($Level eq "Source") {
14771 $Report_Header .= "Source compatibility";
14772 }
14773 elsif($Level eq "Binary") {
14774 $Report_Header .= "Binary compatibility";
14775 }
14776 else {
14777 $Report_Header .= "API compatibility";
14778 }
14779 $Report_Header .= " report for the <span style='color:Blue;'>$TargetLibraryFName</span> $TargetComponent</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014780 $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>";
14781 if($AppPath) {
14782 $Report_Header .= " <span class='nowrap'>&#160;(relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)</span>";
14783 }
14784 $Report_Header .= "</h1>\n";
14785 return $Report_Header;
14786}
14787
14788sub get_SourceInfo()
14789{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014790 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014791 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014792 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014793 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014794 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014795 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
14796 $CheckedHeaders .= "<div class='h_list'>\n";
14797 foreach my $Header_Path (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
14798 {
14799 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
14800 my $Name = get_filename($Identity);
14801 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
14802 $CheckedHeaders .= $Name.$Comment."<br/>\n";
14803 }
14804 $CheckedHeaders .= "</div>\n";
14805 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014806 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014807
14808 if(my @Sources = keys(%{$Registered_Sources{1}}))
14809 {
14810 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
14811 $CheckedSources .= "<div class='h_list'>\n";
14812 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
14813 {
14814 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
14815 my $Name = get_filename($Identity);
14816 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
14817 $CheckedSources .= $Name.$Comment."<br/>\n";
14818 }
14819 $CheckedSources .= "</div>\n";
14820 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
14821 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014822 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014823 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014824 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014825 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014826 $CheckedLibs .= "<div class='lib_list'>\n";
14827 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
14828 {
14829 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
14830 $CheckedLibs .= $Library."<br/>\n";
14831 }
14832 $CheckedLibs .= "</div>\n";
14833 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014834 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014835 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
14836}
14837
14838sub get_ObjTitle()
14839{
14840 if(defined $UsedDump{1}{"DWARF"}) {
14841 return "Objects";
14842 }
14843 else {
14844 return ucfirst($SLIB_TYPE)." Libraries";
14845 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014846}
14847
14848sub get_TypeProblems_Count($$$)
14849{
14850 my ($TypeChanges, $TargetPriority, $Level) = @_;
14851 my $Type_Problems_Count = 0;
14852 foreach my $Type_Name (sort keys(%{$TypeChanges}))
14853 {
14854 my %Kinds_Target = ();
14855 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
14856 {
14857 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
14858 {
14859 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
14860 my $Priority = getProblemSeverity($Level, $Kind);
14861 next if($Priority ne $TargetPriority);
14862 if($Kinds_Target{$Kind}{$Target}) {
14863 next;
14864 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014865 if(cmpSeverities($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014866 { # select a problem with the highest priority
14867 next;
14868 }
14869 $Kinds_Target{$Kind}{$Target} = 1;
14870 $Type_Problems_Count += 1;
14871 }
14872 }
14873 }
14874 return $Type_Problems_Count;
14875}
14876
14877sub get_Summary($)
14878{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014879 my $Level = $_[0];
14880 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014881 $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 +040014882 %{$RESULT{$Level}} = (
14883 "Problems"=>0,
14884 "Warnings"=>0,
14885 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014886 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014887 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014888 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014889 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014890 {
14891 if(not defined $CompatRules{$Level}{$Kind})
14892 { # unknown rule
14893 if(not $UnknownRules{$Level}{$Kind})
14894 { # only one warning
14895 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
14896 $UnknownRules{$Level}{$Kind}=1;
14897 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014898 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014899 }
14900 }
14901 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014902 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
14903 {
14904 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
14905 {
14906 if(not defined $CompatRules{$Level}{$Kind})
14907 { # unknown rule
14908 if(not $UnknownRules{$Level}{$Kind})
14909 { # only one warning
14910 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
14911 $UnknownRules{$Level}{$Kind}=1;
14912 }
14913 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
14914 }
14915 }
14916 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014917 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014918 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014919 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014920 {
14921 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
14922 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014923 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014924 {
14925 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014926 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014927 $Added += 1;
14928 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014929 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014930 {
14931 $Removed += 1;
14932 $TotalAffected{$Level}{$Interface} = $Priority;
14933 }
14934 else
14935 {
14936 if($Priority eq "Safe") {
14937 $I_Other += 1;
14938 }
14939 elsif($Priority eq "High") {
14940 $I_Problems_High += 1;
14941 }
14942 elsif($Priority eq "Medium") {
14943 $I_Problems_Medium += 1;
14944 }
14945 elsif($Priority eq "Low") {
14946 $I_Problems_Low += 1;
14947 }
14948 if(($Priority ne "Low" or $StrictCompat)
14949 and $Priority ne "Safe") {
14950 $TotalAffected{$Level}{$Interface} = $Priority;
14951 }
14952 }
14953 }
14954 }
14955 }
14956 }
14957 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014958 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014959 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014960 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014961 {
14962 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
14963 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014964 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014965 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014966 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
14967 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014968 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014969 if(cmpSeverities($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014970 { # select a problem with the highest priority
14971 next;
14972 }
14973 if(($Priority ne "Low" or $StrictCompat)
14974 and $Priority ne "Safe") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014975 $TotalAffected{$Level}{$Interface} = maxSeverity($TotalAffected{$Level}{$Interface}, $Priority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014976 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014977 %{$TypeChanges{$Type_Name}{$Kind}{$Location}} = %{$CompatProblems{$Level}{$Interface}{$Kind}{$Location}};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014978 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = maxSeverity($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014979 }
14980 }
14981 }
14982 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014983
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014984 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
14985 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
14986 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
14987 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014988
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014989 if($CheckObjectsOnly)
14990 { # only removed exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014991 $RESULT{$Level}{"Affected"} = $Removed*100/keys(%{$Symbol_Library{1}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014992 }
14993 else
14994 { # changed and removed public symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014995 my $SCount = keys(%{$CheckedSymbols{$Level}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014996 if($ExtendedCheck)
14997 { # don't count external_func_0 for constants
14998 $SCount-=1;
14999 }
15000 if($SCount)
15001 {
15002 my %Weight = (
15003 "High" => 100,
15004 "Medium" => 50,
15005 "Low" => 25
15006 );
15007 foreach (keys(%{$TotalAffected{$Level}})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015008 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015009 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015010 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015011 }
15012 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015013 $RESULT{$Level}{"Affected"} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015014 }
15015 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015016 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15017 if($RESULT{$Level}{"Affected"}>=100) {
15018 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015019 }
15020
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015021 $RESULT{$Level}{"Problems"} += $Removed;
15022 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015023 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015024 if($StrictCompat) {
15025 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15026 }
15027 else {
15028 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15029 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015030
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015031 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015032 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015033 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015034 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015035 my $Severity = getProblemSeverity($Level, $Kind);
15036 if($Severity eq "Safe")
15037 {
15038 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015039 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015040 elsif($Severity eq "Low")
15041 {
15042 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015043 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015044 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015045 }
15046
15047 if($C_Problems_Low)
15048 {
15049 if($StrictCompat) {
15050 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15051 }
15052 else {
15053 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015054 }
15055 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015056 if($CheckImpl and $Level eq "Binary")
15057 {
15058 if($StrictCompat) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015059 $RESULT{$Level}{"Problems"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015060 }
15061 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015062 $RESULT{$Level}{"Warnings"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015063 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015064 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015065 if($RESULT{$Level}{"Problems"}
15066 and $RESULT{$Level}{"Affected"}) {
15067 $RESULT{$Level}{"Verdict"} = "incompatible";
15068 }
15069 else {
15070 $RESULT{$Level}{"Verdict"} = "compatible";
15071 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015072
15073 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15074 if(not $TotalTypes)
15075 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015076 $TotalTypes = keys(%{$TName_Tid{1}});
15077 }
15078
15079 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15080 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15081
15082 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15083
15084 if($ReportFormat eq "xml")
15085 { # XML
15086 # test info
15087 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15088 $TestInfo .= " <version1>\n";
15089 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
15090 $TestInfo .= " <architecture>$Arch1</architecture>\n";
15091 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15092 $TestInfo .= " </version1>\n";
15093
15094 $TestInfo .= " <version2>\n";
15095 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
15096 $TestInfo .= " <architecture>$Arch2</architecture>\n";
15097 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15098 $TestInfo .= " </version2>\n";
15099 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15100
15101 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015102 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015103 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015104 $TestResults .= " <headers>\n";
15105 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15106 {
15107 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15108 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15109 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15110 }
15111 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015112 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015113
15114 if(my @Sources = keys(%{$Registered_Sources{1}}))
15115 {
15116 $TestResults .= " <sources>\n";
15117 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15118 {
15119 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15120 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15121 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15122 }
15123 $TestResults .= " </sources>\n";
15124 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015125
15126 $TestResults .= " <libs>\n";
15127 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15128 {
15129 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15130 $TestResults .= " <name>$Library</name>\n";
15131 }
15132 $TestResults .= " </libs>\n";
15133
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015134 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015135 $TestResults .= " <types>".$TotalTypes."</types>\n";
15136
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015137 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15138 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015139 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15140
15141 # problem summary
15142 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15143 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15144
15145 $Problem_Summary .= " <problems_with_types>\n";
15146 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15147 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15148 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15149 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15150 $Problem_Summary .= " </problems_with_types>\n";
15151
15152 $Problem_Summary .= " <problems_with_symbols>\n";
15153 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15154 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15155 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015156 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015157 $Problem_Summary .= " </problems_with_symbols>\n";
15158
15159 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015160 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015161 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015162 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015163 {
15164 $Problem_Summary .= " <impl>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015165 $Problem_Summary .= " <low>".keys(%CompatProblems_Impl)."</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015166 $Problem_Summary .= " </impl>\n";
15167 }
15168 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15169
15170 return ($TestInfo.$TestResults.$Problem_Summary, "");
15171 }
15172 else
15173 { # HTML
15174 # test info
15175 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015176 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015177 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetLibraryFName</td></tr>\n";
15178
15179 my (@VInf1, @VInf2, $AddTestInfo) = ();
15180 if($Arch1 ne "unknown"
15181 and $Arch2 ne "unknown")
15182 { # CPU arch
15183 if($Arch1 eq $Arch2)
15184 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015185 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015186 }
15187 else
15188 { # go to the version number
15189 push(@VInf1, showArch($Arch1));
15190 push(@VInf2, showArch($Arch2));
15191 }
15192 }
15193 if($GccV1 ne "unknown"
15194 and $GccV2 ne "unknown"
15195 and $OStarget ne "windows")
15196 { # GCC version
15197 if($GccV1 eq $GccV2)
15198 { # go to the separate section
15199 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15200 }
15201 else
15202 { # go to the version number
15203 push(@VInf1, "gcc ".$GccV1);
15204 push(@VInf2, "gcc ".$GccV2);
15205 }
15206 }
15207 # show long version names with GCC version and CPU architecture name (if different)
15208 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
15209 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
15210 $TestInfo .= $AddTestInfo;
15211 #if($COMMON_LANGUAGE{1}) {
15212 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
15213 #}
15214 if($ExtendedCheck) {
15215 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
15216 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015217 if($JoinReport)
15218 {
15219 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015220 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015221 }
15222 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015223 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015224 }
15225 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015226 $TestInfo .= "</table>\n";
15227
15228 # test results
15229 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015230 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015231
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015232 if(my @Headers = keys(%{$Registered_Headers{1}}))
15233 {
15234 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
15235 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
15236 }
15237 elsif($CheckObjectsOnly) {
15238 $TestResults .= "<tr><th>Total Header Files</th><td>0&#160;(not&#160;analyzed)</td></tr>\n";
15239 }
15240
15241 if(my @Sources = keys(%{$Registered_Sources{1}}))
15242 {
15243 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
15244 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
15245 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015246
15247 if(not $ExtendedCheck)
15248 {
15249 my $Libs_Link = "0";
15250 $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 +040015251 $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 +040015252 }
15253
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015254 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015255
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015256 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015257 if($JoinReport) {
15258 $META_DATA = "kind:".lc($Level).";".$META_DATA;
15259 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015260 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015261 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015262 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
15263 }
15264 else {
15265 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
15266 }
15267 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015268 $TestResults .= "</table>\n";
15269
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015270 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015271 # problem summary
15272 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015273 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015274 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
15275
15276 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015277 if($Added>0)
15278 {
15279 if($JoinReport) {
15280 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
15281 }
15282 else {
15283 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
15284 }
15285 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015286 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015287 $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 +040015288
15289 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015290 if($Removed>0)
15291 {
15292 if($JoinReport) {
15293 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
15294 }
15295 else {
15296 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
15297 }
15298 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015299 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015300 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
15301 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015302
15303 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015304 $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 +040015305 $TH_Link = "n/a" if($CheckObjectsOnly);
15306 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015307 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
15308 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015309
15310 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015311 $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 +040015312 $TM_Link = "n/a" if($CheckObjectsOnly);
15313 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015314 $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 +040015315
15316 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015317 $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 +040015318 $TL_Link = "n/a" if($CheckObjectsOnly);
15319 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015320 $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 +040015321
15322 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015323 $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 +040015324 $IH_Link = "n/a" if($CheckObjectsOnly);
15325 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015326 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
15327 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015328
15329 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015330 $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 +040015331 $IM_Link = "n/a" if($CheckObjectsOnly);
15332 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015333 $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 +040015334
15335 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015336 $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 +040015337 $IL_Link = "n/a" if($CheckObjectsOnly);
15338 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015339 $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 +040015340
15341 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015342 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
15343 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015344 }
15345 $ChangedConstants_Link = "n/a" if($CheckObjectsOnly);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015346 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015347 $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 +040015348
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015349 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015350 {
15351 my $ChangedImpl_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015352 $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 +040015353 $ChangedImpl_Link = "n/a" if($CheckHeadersOnly);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015354 $META_DATA .= "changed_implementation:".keys(%CompatProblems_Impl).";";
15355 $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 +040015356 }
15357 # Safe Changes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015358 if($T_Other and not $CheckObjectsOnly)
15359 {
15360 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015361 $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 +040015362 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015363
15364 if($I_Other and not $CheckObjectsOnly)
15365 {
15366 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015367 $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 +040015368 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015369
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015370 if($C_Other and not $CheckObjectsOnly)
15371 {
15372 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
15373 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
15374 }
15375
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015376 $META_DATA .= "tool_version:$TOOL_VERSION";
15377 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015378 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015379 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
15380 }
15381}
15382
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015383sub getStyle($$$)
15384{
15385 my ($Subj, $Act, $Num) = @_;
15386 my %Style = (
15387 "A"=>"new",
15388 "R"=>"failed",
15389 "S"=>"passed",
15390 "L"=>"warning",
15391 "M"=>"failed",
15392 "H"=>"failed"
15393 );
15394 if($Num>0) {
15395 return " class='".$Style{$Act}."'";
15396 }
15397 return "";
15398}
15399
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015400sub show_number($)
15401{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015402 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015403 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015404 my $Num = cut_off_number($_[0], 2, 0);
15405 if($Num eq "0")
15406 {
15407 foreach my $P (3 .. 7)
15408 {
15409 $Num = cut_off_number($_[0], $P, 1);
15410 if($Num ne "0") {
15411 last;
15412 }
15413 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015414 }
15415 if($Num eq "0") {
15416 $Num = $_[0];
15417 }
15418 return $Num;
15419 }
15420 return $_[0];
15421}
15422
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015423sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015424{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015425 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015426 if($num!~/\./)
15427 {
15428 $num .= ".";
15429 foreach (1 .. $digs_to_cut-1) {
15430 $num .= "0";
15431 }
15432 }
15433 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
15434 {
15435 foreach (1 .. $digs_to_cut - 1 - length($1)) {
15436 $num .= "0";
15437 }
15438 }
15439 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
15440 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
15441 }
15442 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015443 if($z) {
15444 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
15445 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015446 return $num;
15447}
15448
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015449sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015450{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015451 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015452 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015453
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015454 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015455 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
15456 {
15457 my $Header = $Constants{1}{$Constant}{"Header"};
15458 if(not $Header)
15459 { # added
15460 $Header = $Constants{2}{$Constant}{"Header"}
15461 }
15462
15463 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15464 {
15465 if(not defined $CompatRules{$Level}{$Kind}) {
15466 next;
15467 }
15468 if($TargetSeverity ne getProblemSeverity($Level, $Kind)) {
15469 next;
15470 }
15471 $ReportMap{$Header}{$Constant}{$Kind} = 1;
15472 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015473 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015474
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015475 if($ReportFormat eq "xml")
15476 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015477 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015478 {
15479 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015480 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015481 {
15482 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015483 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
15484 {
15485 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
15486 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
15487 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015488
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015489 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
15490 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
15491 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
15492 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
15493 $CHANGED_CONSTANTS .= " </problem>\n";
15494 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015495 $CHANGED_CONSTANTS .= " </constant>\n";
15496 }
15497 $CHANGED_CONSTANTS .= " </header>\n";
15498 }
15499 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
15500 }
15501 else
15502 { # HTML
15503 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015504 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015505 {
15506 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015507 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015508 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015509 my $Report = "";
15510
15511 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
15512 {
15513 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
15514 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
15515 $Report .= "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
15516 $Number += 1;
15517 }
15518 if($Report)
15519 {
15520 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n";
15521 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
15522 $Report = insertIDs($Report);
15523 }
15524 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015525 }
15526 $CHANGED_CONSTANTS .= "<br/>\n";
15527 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015528 if($CHANGED_CONSTANTS)
15529 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015530 my $Title = "Problems with Constants, $TargetSeverity Severity";
15531 if($TargetSeverity eq "Safe")
15532 { # Safe Changes
15533 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015534 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015535 $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 +040015536 }
15537 }
15538 return $CHANGED_CONSTANTS;
15539}
15540
15541sub get_Report_Impl()
15542{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015543 my $CHANGED_IMPLEMENTATION = "";
15544 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015545 foreach my $Interface (sort keys(%CompatProblems_Impl))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015546 {
15547 my $HeaderName = $CompleteSignature{1}{$Interface}{"Header"};
15548 my $DyLib = $Symbol_Library{1}{$Interface};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015549 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015550 }
15551 my $Changed_Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015552 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015553 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015554 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015555 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015556 my %NameSpaceSymbols = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015557 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015558 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015559 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015560 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015561 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015562 $CHANGED_IMPLEMENTATION .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015563 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015564 foreach my $Interface (@SortedInterfaces)
15565 {
15566 $Changed_Number += 1;
15567 my $Signature = get_Signature($Interface, 1);
15568 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015569 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015570 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015571 $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 +040015572 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015573 $CHANGED_IMPLEMENTATION .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015574 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015575 }
15576 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015577 if($CHANGED_IMPLEMENTATION)
15578 {
15579 $CHANGED_IMPLEMENTATION = insertIDs($CHANGED_IMPLEMENTATION);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015580 $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 +040015581 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015582
15583 # clean memory
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015584 %CompatProblems_Impl = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015585
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015586 return $CHANGED_IMPLEMENTATION;
15587}
15588
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015589sub getTitle($$$)
15590{
15591 my ($Header, $Library, $NameSpace) = @_;
15592 my $Title = "";
15593 if($Library and $Library!~/\.\w+\Z/) {
15594 $Library .= " (.$LIB_EXT)";
15595 }
15596 if($Header and $Library)
15597 {
15598 $Title .= "<span class='h_name'>$Header</span>";
15599 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
15600 }
15601 elsif($Library) {
15602 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
15603 }
15604 elsif($Header) {
15605 $Title .= "<span class='h_name'>$Header</span><br/>\n";
15606 }
15607 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015608 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015609 }
15610 return $Title;
15611}
15612
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015613sub get_Report_Added($)
15614{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015615 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015616 my $ADDED_INTERFACES = "";
15617 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015618 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015619 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015620 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015621 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015622 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015623 {
15624 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
15625 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015626 if($Level eq "Source" and $ReportFormat eq "html")
15627 { # do not show library name in HTML report
15628 $DyLib = "";
15629 }
15630 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015631 }
15632 }
15633 }
15634 if($ReportFormat eq "xml")
15635 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015636 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015637 {
15638 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015639 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015640 {
15641 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015642 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015643 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
15644 }
15645 $ADDED_INTERFACES .= " </library>\n";
15646 }
15647 $ADDED_INTERFACES .= " </header>\n";
15648 }
15649 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
15650 }
15651 else
15652 { # HTML
15653 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015654 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015655 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015656 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015657 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015658 my %NameSpaceSymbols = ();
15659 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015660 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015661 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015662 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015663 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015664 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
15665 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015666 foreach my $Interface (@SortedInterfaces)
15667 {
15668 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015669 my $Signature = get_Signature($Interface, 2);
15670 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015671 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015672 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040015673 if($Interface=~/\A(_Z|\?)/)
15674 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015675 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015676 $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 +040015677 }
15678 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015679 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015680 }
15681 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040015682 else
15683 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015684 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015685 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015686 }
15687 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015688 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015689 }
15690 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015691 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015692 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015693 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015694 }
15695 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015696 if($ADDED_INTERFACES)
15697 {
15698 my $Anchor = "<a name='Added'></a>";
15699 if($JoinReport) {
15700 $Anchor = "<a name='".$Level."_Added'></a>";
15701 }
15702 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015703 }
15704 }
15705 return $ADDED_INTERFACES;
15706}
15707
15708sub get_Report_Removed($)
15709{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015710 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015711 my $REMOVED_INTERFACES = "";
15712 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015713 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015714 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015715 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015716 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015717 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015718 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015719 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
15720 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015721 if($Level eq "Source" and $ReportFormat eq "html")
15722 { # do not show library name in HTML report
15723 $DyLib = "";
15724 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015725 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015726 }
15727 }
15728 }
15729 if($ReportFormat eq "xml")
15730 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015731 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015732 {
15733 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015734 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015735 {
15736 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015737 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
15738 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015739 }
15740 $REMOVED_INTERFACES .= " </library>\n";
15741 }
15742 $REMOVED_INTERFACES .= " </header>\n";
15743 }
15744 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
15745 }
15746 else
15747 { # HTML
15748 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015749 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015750 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015751 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015752 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015753 my %NameSpaceSymbols = ();
15754 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040015755 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015756 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015757 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015758 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015759 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
15760 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015761 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015762 {
15763 $Removed_Number += 1;
15764 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015765 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015766 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015767 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015768 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015769 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015770 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015771 if($Signature) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015772 $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 +040015773 }
15774 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015775 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015776 }
15777 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015778 else
15779 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015780 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015781 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015782 }
15783 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015784 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015785 }
15786 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015787 }
15788 }
15789 $REMOVED_INTERFACES .= "<br/>\n";
15790 }
15791 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015792 if($REMOVED_INTERFACES)
15793 {
15794 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
15795 if($JoinReport) {
15796 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
15797 }
15798 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015799 }
15800 }
15801 return $REMOVED_INTERFACES;
15802}
15803
15804sub getXmlParams($$)
15805{
15806 my ($Content, $Problem) = @_;
15807 return "" if(not $Content or not $Problem);
15808 my %XMLparams = ();
15809 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
15810 {
15811 my $Macro = "\@".lc($Attr);
15812 if($Content=~/\Q$Macro\E/) {
15813 $XMLparams{lc($Attr)} = $Problem->{$Attr};
15814 }
15815 }
15816 my @PString = ();
15817 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015818 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015819 }
15820 if(@PString) {
15821 return " ".join(" ", @PString);
15822 }
15823 else {
15824 return "";
15825 }
15826}
15827
15828sub addMarkup($)
15829{
15830 my $Content = $_[0];
15831 # auto-markup
15832 $Content=~s/\n[ ]*//; # spaces
15833 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
15834 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015835 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015836 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
15837 if($Content=~/\ANOTE:/)
15838 { # notes
15839 $Content=~s!(NOTE):!<b>$1</b>:!g;
15840 }
15841 else {
15842 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
15843 }
15844 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
15845 my @Keywords = (
15846 "void",
15847 "const",
15848 "static",
15849 "restrict",
15850 "volatile",
15851 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015852 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015853 );
15854 my $MKeys = join("|", @Keywords);
15855 foreach (@Keywords) {
15856 $MKeys .= "|non-".$_;
15857 }
15858 $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 +040015859
15860 # Markdown
15861 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
15862 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015863 return $Content;
15864}
15865
15866sub applyMacroses($$$$)
15867{
15868 my ($Level, $Kind, $Content, $Problem) = @_;
15869 return "" if(not $Content or not $Problem);
15870 $Problem->{"Word_Size"} = $WORD_SIZE{2};
15871 $Content = addMarkup($Content);
15872 # macros
15873 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
15874 {
15875 my $Macro = "\@".lc($Attr);
15876 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015877 if(not defined $Value
15878 or $Value eq "") {
15879 next;
15880 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015881 if($Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015882 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015883 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
15884 $Value=~s/\s\w+(\)|,)/$1/g; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015885 $Value = black_name($Value);
15886 }
15887 elsif($Value=~/\s/) {
15888 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
15889 }
15890 elsif($Value=~/\A\d+\Z/
15891 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
15892 { # bits to bytes
15893 if($Value % $BYTE_SIZE)
15894 { # bits
15895 if($Value==1) {
15896 $Value = "<b>".$Value."</b> bit";
15897 }
15898 else {
15899 $Value = "<b>".$Value."</b> bits";
15900 }
15901 }
15902 else
15903 { # bytes
15904 $Value /= $BYTE_SIZE;
15905 if($Value==1) {
15906 $Value = "<b>".$Value."</b> byte";
15907 }
15908 else {
15909 $Value = "<b>".$Value."</b> bytes";
15910 }
15911 }
15912 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015913 else
15914 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015915 $Value = "<b>".htmlSpecChars($Value)."</b>";
15916 }
15917 $Content=~s/\Q$Macro\E/$Value/g;
15918 }
15919
15920 if($Content=~/(\A|[^\@\w])\@\w/)
15921 {
15922 if(not $IncompleteRules{$Level}{$Kind})
15923 { # only one warning
15924 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
15925 $IncompleteRules{$Level}{$Kind} = 1;
15926 }
15927 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015928 return $Content;
15929}
15930
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015931sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015932{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015933 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015934 my $INTERFACE_PROBLEMS = "";
15935 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015936 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015937 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015938 my ($SN, $SS, $SV) = separate_symbol($Symbol);
15939 if($SV and defined $CompatProblems{$Level}{$SN}) {
15940 next;
15941 }
15942 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015943 {
15944 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015945 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015946 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015947 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
15948 my $DyLib = $Symbol_Library{1}{$Symbol};
15949 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015950 { # Symbol with Version
15951 $DyLib = $Symbol_Library{1}{$VSym};
15952 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015953 if(not $DyLib)
15954 { # const global data
15955 $DyLib = "";
15956 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015957 if($Level eq "Source" and $ReportFormat eq "html")
15958 { # do not show library name in HTML report
15959 $DyLib = "";
15960 }
15961 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
15962 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015963 {
15964 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015965 if($Priority ne $TargetSeverity) {
15966 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015967 }
15968 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015969 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
15970 {
15971 delete($SymbolChanges{$Symbol}{$Kind});
15972 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015973 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015974 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015975 }
15976 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015977 if(not keys(%{$SymbolChanges{$Symbol}})) {
15978 delete($SymbolChanges{$Symbol});
15979 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015980 }
15981 if($ReportFormat eq "xml")
15982 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015983 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015984 {
15985 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015986 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015987 {
15988 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015989 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 +040015990 {
15991 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
15992 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
15993 {
15994 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
15995 {
15996 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015997 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015998 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
15999 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16000 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16001 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16002 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
16003 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
16004 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16005 $INTERFACE_PROBLEMS .= " </problem>\n";
16006 }
16007 }
16008 $INTERFACE_PROBLEMS .= " </symbol>\n";
16009 }
16010 $INTERFACE_PROBLEMS .= " </library>\n";
16011 }
16012 $INTERFACE_PROBLEMS .= " </header>\n";
16013 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016014 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016015 }
16016 else
16017 { # HTML
16018 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016019 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016020 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016021 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016022 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016023 my (%NameSpaceSymbols, %NewSignature) = ();
16024 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016025 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016026 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016027 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016028 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016029 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016030 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 +040016031 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016032 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016033 my $Signature = get_Signature($Symbol, 1);
16034 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016035 my $ProblemNum = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016036 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016037 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016038 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016039 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016040 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016041 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016042 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016043 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016044 }
16045 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16046 {
16047 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016048 $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 +040016049 $ProblemNum += 1;
16050 $ProblemsNum += 1;
16051 }
16052 }
16053 }
16054 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016055 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016056 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016057 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016058 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016059 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016060 }
16061 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016062 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016063 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016064 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16065 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16066 if($NewSignature{$Symbol})
16067 { # argument list changed to
16068 $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 +040016069 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016070 if($Symbol=~/\A(_Z|\?)/) {
16071 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16072 }
16073 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n";
16074 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016075 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016076 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016077 }
16078 }
16079 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016080 $INTERFACE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016081 }
16082 }
16083 }
16084 if($INTERFACE_PROBLEMS)
16085 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016086 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16087 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16088 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016089 { # Safe Changes
16090 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016091 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016092 $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 +040016093 }
16094 }
16095 return $INTERFACE_PROBLEMS;
16096}
16097
16098sub get_Report_TypeProblems($$)
16099{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016100 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016101 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016102 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016103 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016104 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016105 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016106 {
16107 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16108 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016109 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016110 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016111 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016112 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016113 my $Severity = getProblemSeverity($Level, $Kind);
16114 if($Severity eq "Safe"
16115 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016116 next;
16117 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016118
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016119 if(cmpSeverities($Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target}, $Severity))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016120 { # select a problem with the highest priority
16121 next;
16122 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016123 %{$TypeChanges{$TypeName}{$Kind}{$Location}} = %{$CompatProblems{$Level}{$Interface}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016124 }
16125 }
16126 }
16127 }
16128 my %Kinds_Locations = ();
16129 foreach my $TypeName (keys(%TypeChanges))
16130 {
16131 my %Kinds_Target = ();
16132 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16133 {
16134 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
16135 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016136 my $Severity = getProblemSeverity($Level, $Kind);
16137 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016138 { # other priority
16139 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16140 next;
16141 }
16142 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16143 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
16144 if($Kinds_Target{$Kind}{$Target})
16145 { # duplicate target
16146 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16147 next;
16148 }
16149 $Kinds_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016150 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016151 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016152 }
16153 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16154 delete($TypeChanges{$TypeName}{$Kind});
16155 }
16156 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016157 if(not keys(%{$TypeChanges{$TypeName}})) {
16158 delete($TypeChanges{$TypeName});
16159 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016160 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016161 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 +040016162 if($ReportFormat eq "xml")
16163 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016164 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016165 {
16166 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016167 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016168 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016169 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016170 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16171 {
16172 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
16173 {
16174 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16175 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16176 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16177 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16178 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16179 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
16180 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
16181 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16182 $TYPE_PROBLEMS .= " </problem>\n";
16183 }
16184 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016185 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016186 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016187 $TYPE_PROBLEMS .= showVTables($TypeName);
16188 }
16189 $TYPE_PROBLEMS .= " </type>\n";
16190 }
16191 $TYPE_PROBLEMS .= " </header>\n";
16192 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016193 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016194 }
16195 else
16196 { # HTML
16197 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016198 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016199 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016200 my (%NameSpace_Type) = ();
16201 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016202 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016203 }
16204 foreach my $NameSpace (sort keys(%NameSpace_Type))
16205 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016206 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016207 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 +040016208 foreach my $TypeName (@SortedTypes)
16209 {
16210 my $ProblemNum = 1;
16211 my $TYPE_REPORT = "";
16212 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16213 {
16214 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
16215 {
16216 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16217 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16218 {
16219 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
16220 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16221 $ProblemNum += 1;
16222 $ProblemsNum += 1;
16223 }
16224 }
16225 }
16226 $ProblemNum -= 1;
16227 if($TYPE_REPORT)
16228 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016229 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016230 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016231 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016232 $ShowVTables = showVTables($TypeName);
16233 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016234
16235 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016236 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
16237 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
16238 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
16239 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016240 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016241 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016242 }
16243 }
16244 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016245 $TYPE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016246 }
16247 }
16248 if($TYPE_PROBLEMS)
16249 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016250 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
16251 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016252 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016253 { # Safe Changes
16254 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016255 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016256 $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 +040016257 }
16258 }
16259 return $TYPE_PROBLEMS;
16260}
16261
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016262sub show_Type($$$)
16263{
16264 my ($Name, $Html, $LibVersion) = @_;
16265 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
16266 $TType = lc($TType);
16267 if($TType=~/struct|union|enum/) {
16268 $Name=~s/\A\Q$TType\E //g;
16269 }
16270 if($Html) {
16271 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
16272 }
16273 else {
16274 $Name = $TType." ".$Name;
16275 }
16276 return $Name;
16277}
16278
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016279sub get_Anchor($$$)
16280{
16281 my ($Kind, $Level, $Severity) = @_;
16282 if($JoinReport)
16283 {
16284 if($Severity eq "Safe") {
16285 return "Other_".$Level."_Changes_In_".$Kind."s";
16286 }
16287 else {
16288 return $Kind."_".$Level."_Problems_".$Severity;
16289 }
16290 }
16291 else
16292 {
16293 if($Severity eq "Safe") {
16294 return "Other_Changes_In_".$Kind."s";
16295 }
16296 else {
16297 return $Kind."_Problems_".$Severity;
16298 }
16299 }
16300}
16301
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016302sub showVTables($)
16303{
16304 my $TypeName = $_[0];
16305 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016306 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016307 if(defined $Type1{"VTable"}
16308 and keys(%{$Type1{"VTable"}}))
16309 {
16310 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016311 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016312 if(defined $Type2{"VTable"}
16313 and keys(%{$Type2{"VTable"}}))
16314 {
16315 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
16316 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016317 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016318 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016319 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
16320 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016321 }
16322 my $VTABLES = "";
16323 if($ReportFormat eq "xml")
16324 { # XML
16325 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016326 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016327 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016328 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016329 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
16330 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016331 $VTABLES .= " </entry>\n";
16332 }
16333 $VTABLES .= " </vtable>\n\n";
16334 }
16335 else
16336 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016337 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016338 $VTABLES .= "<tr><th width='2%'>Offset</th>";
16339 $VTABLES .= "<th width='45%'>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
16340 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016341 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016342 {
16343 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016344 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016345 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016346 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016347 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016348 $Color1 = " class='failed'";
16349 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016350 }
16351 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016352 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016353 }
16354 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016355 $VTABLES .= "<tr><th>".$Index."</th>\n";
16356 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
16357 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016358 }
16359 $VTABLES .= "</table><br/>\n";
16360 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016361 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016362 }
16363 return $VTABLES;
16364 }
16365 }
16366 return "";
16367}
16368
16369sub simpleVEntry($)
16370{
16371 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016372 if(not defined $VEntry
16373 or $VEntry eq "") {
16374 return "";
16375 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016376 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
16377 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
16378 if($VEntry=~/\A_ZThn.+\Z/) {
16379 $VEntry = "non-virtual thunk";
16380 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016381 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016382 # support for old GCC versions
16383 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
16384 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
16385 $VEntry=~s/\A&_Z\Z/& _Z/;
16386 # templates
16387 if($VEntry=~s/ \[with (\w+) = (.+?)(, [^=]+ = .+|])\Z//g)
16388 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
16389 # become std::basic_streambuf<char, ...>::imbue
16390 my ($Pname, $Pval) = ($1, $2);
16391 if($Pname eq "_CharT" and $VEntry=~/\Astd::/)
16392 { # stdc++ typedefs
16393 $VEntry=~s/<$Pname(, [^<>]+|)>/<$Pval>/g;
16394 # FIXME: simplify names using stdcxx typedefs (StdCxxTypedef)
16395 # The typedef info should be added to ABI dumps
16396 }
16397 else
16398 {
16399 $VEntry=~s/<$Pname>/<$Pval>/g;
16400 $VEntry=~s/<$Pname, [^<>]+>/<$Pval, ...>/g;
16401 }
16402 }
16403 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
16404 return $VEntry;
16405}
16406
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016407sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016408{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016409 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016410 my $LIMIT = 1000;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016411 if($#{$Syms}>=10000)
16412 { # reduce size of the report
16413 $LIMIT = 10;
16414 }
16415 my %SProblems = ();
16416 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016417 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016418 if(keys(%SProblems)>$LIMIT) {
16419 last;
16420 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016421 if(($Symbol=~/C2E|D2E|D0E/))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016422 { # duplicated problems for C2 constructors, D2 and D0 destructors
16423 next;
16424 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016425 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16426 if($Level eq "Source")
16427 { # remove symbol version
16428 $Symbol=$SN;
16429 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016430 my ($MinPath_Length, $ProblemLocation_Last) = (-1, "");
16431 my $Severity_Max = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016432 my $Signature = get_Signature($Symbol, 1);
16433 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016434 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016435 foreach my $Location (keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016436 {
16437 if(not defined $Kinds_Locations->{$Kind}
16438 or not $Kinds_Locations->{$Kind}{$Location}) {
16439 next;
16440 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016441 if($SV and defined $CompatProblems{$Level}{$SN}
16442 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Location})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016443 { # duplicated problems for versioned symbols
16444 next;
16445 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016446 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016447 next if($Type_Name ne $Target_TypeName);
16448
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016449 my $Position = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Param_Pos"};
16450 my $Param_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Param_Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016451 my $Severity = getProblemSeverity($Level, $Kind);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016452 my $Path_Length = 0;
16453 my $ProblemLocation = $Location;
16454 if($Type_Name) {
16455 $ProblemLocation=~s/->\Q$Type_Name\E\Z//g;
16456 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016457 while($ProblemLocation=~/\-\>/g) {
16458 $Path_Length += 1;
16459 }
16460 if($MinPath_Length==-1 or ($Path_Length<=$MinPath_Length and $Severity_Val{$Severity}>$Severity_Max)
16461 or (cmp_locations($ProblemLocation, $ProblemLocation_Last) and $Severity_Val{$Severity}==$Severity_Max))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016462 {
16463 $MinPath_Length = $Path_Length;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016464 $Severity_Max = $Severity_Val{$Severity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016465 $ProblemLocation_Last = $ProblemLocation;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016466 %{$SProblems{$Symbol}} = (
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016467 "Descr"=>getAffectDescription($Level, $Symbol, $Kind, $Location),
16468 "Severity_Max"=>$Severity_Max,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016469 "Signature"=>$Signature,
16470 "Position"=>$Position,
16471 "Param_Name"=>$Param_Name,
16472 "Location"=>$Location
16473 );
16474 }
16475 }
16476 }
16477 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016478 my @Symbols = keys(%SProblems);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016479 @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 +040016480 @Symbols = sort {$SProblems{$b}{"Severity_Max"}<=>$SProblems{$a}{"Severity_Max"}} @Symbols;
16481 if($#Symbols+1>$LIMIT)
16482 { # remove last element
16483 pop(@Symbols);
16484 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016485 my $Affected = "";
16486 if($ReportFormat eq "xml")
16487 { # XML
16488 $Affected .= " <affected>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016489 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016490 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016491 my $Param_Name = $SProblems{$Symbol}{"Param_Name"};
16492 my $Description = $SProblems{$Symbol}{"Descr"};
16493 my $Location = $SProblems{$Symbol}{"Location"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016494 my $Target = "";
16495 if($Param_Name) {
16496 $Target = " affected=\"param\" param_name=\"$Param_Name\"";
16497 }
16498 elsif($Location=~/\Aretval(\-|\Z)/i) {
16499 $Target = " affected=\"retval\"";
16500 }
16501 elsif($Location=~/\Athis(\-|\Z)/i) {
16502 $Target = " affected=\"this\"";
16503 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016504 $Affected .= " <symbol$Target name=\"$Symbol\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016505 $Affected .= " <comment>".xmlSpecChars($Description)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016506 $Affected .= " </symbol>\n";
16507 }
16508 $Affected .= " </affected>\n";
16509 }
16510 else
16511 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016512 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016513 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016514 my $Description = $SProblems{$Symbol}{"Descr"};
16515 my $Signature = $SProblems{$Symbol}{"Signature"};
16516 my $Pos = $SProblems{$Symbol}{"Position"};
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016517 $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 +040016518 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016519 if(keys(%SProblems)>$LIMIT) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016520 $Affected .= "and others ...<br/>";
16521 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016522 $Affected = "<div class='affected'>".$Affected."</div>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016523 if($Affected)
16524 {
16525 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016526 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".(keys(%SProblems)>$LIMIT?">".$LIMIT:keys(%SProblems)).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016527 }
16528 }
16529 return $Affected;
16530}
16531
16532sub cmp_locations($$)
16533{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016534 my ($L1, $L2) = @_;
16535 if($L2=~/\b(retval|this)\b/
16536 and $L1!~/\b(retval|this)\b/ and $L1!~/\-\>/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016537 return 1;
16538 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016539 if($L2=~/\b(retval|this)\b/ and $L2=~/\-\>/
16540 and $L1!~/\b(retval|this)\b/ and $L1=~/\-\>/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016541 return 1;
16542 }
16543 return 0;
16544}
16545
16546sub getAffectDescription($$$$)
16547{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016548 my ($Level, $Symbol, $Kind, $Location) = @_;
16549 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016550 my $PPos = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016551 my @Sentence = ();
16552 $Location=~s/\A(.*)\-\>.+?\Z/$1/;
16553 if($Kind eq "Overridden_Virtual_Method"
16554 or $Kind eq "Overridden_Virtual_Method_B") {
16555 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
16556 }
16557 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16558 {
16559 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
16560 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016561 my $METHOD_TYPE = $CompleteSignature{1}{$Symbol}{"Constructor"}?"constructor":"method";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016562 my $ClassName = $TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016563 if($ClassName eq $Problem{"Type_Name"}) {
16564 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
16565 }
16566 else {
16567 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
16568 }
16569 }
16570 else
16571 {
16572 if($Location=~/retval/)
16573 { # return value
16574 if($Location=~/\-\>/) {
16575 push(@Sentence, "Field \'".$Location."\' in return value");
16576 }
16577 else {
16578 push(@Sentence, "Return value");
16579 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016580 if(my $Init = $Problem{"InitialType_Type"})
16581 {
16582 if($Init eq "Pointer") {
16583 push(@Sentence, "(pointer)");
16584 }
16585 elsif($Init eq "Ref") {
16586 push(@Sentence, "(reference)");
16587 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016588 }
16589 }
16590 elsif($Location=~/this/)
16591 { # "this" pointer
16592 if($Location=~/\-\>/) {
16593 push(@Sentence, "Field \'".$Location."\' in the object of this method");
16594 }
16595 else {
16596 push(@Sentence, "\'this\' pointer");
16597 }
16598 }
16599 else
16600 { # parameters
16601 if($Location=~/\-\>/) {
16602 push(@Sentence, "Field \'".$Location."\' in $PPos parameter");
16603 }
16604 else {
16605 push(@Sentence, "$PPos parameter");
16606 }
16607 if($Problem{"Param_Name"}) {
16608 push(@Sentence, "\'".$Problem{"Param_Name"}."\'");
16609 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016610 if(my $Init = $Problem{"InitialType_Type"})
16611 {
16612 if($Init eq "Pointer") {
16613 push(@Sentence, "(pointer)");
16614 }
16615 elsif($Init eq "Ref") {
16616 push(@Sentence, "(reference)");
16617 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016618 }
16619 }
16620 if($Location eq "this") {
16621 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
16622 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016623 elsif(defined $Problem{"Start_Type_Name"}
16624 and $Problem{"Start_Type_Name"} eq $Problem{"Type_Name"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016625 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
16626 }
16627 else {
16628 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
16629 }
16630 }
16631 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016632 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016633 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 +040016634 }
16635 return join(" ", @Sentence);
16636}
16637
16638sub get_XmlSign($$)
16639{
16640 my ($Symbol, $LibVersion) = @_;
16641 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
16642 my $Report = "";
16643 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
16644 {
16645 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016646 my $Type = $Info->{"Param"}{$Pos}{"type"};
16647 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016648 foreach my $Typedef (keys(%ChangedTypedef))
16649 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016650 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
16651 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
16652 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016653 }
16654 $Report .= " <param pos=\"$Pos\">\n";
16655 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016656 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016657 $Report .= " </param>\n";
16658 }
16659 if(my $Return = $Info->{"Return"})
16660 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016661 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016662 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016663 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016664 $Report .= " </retval>\n";
16665 }
16666 return $Report;
16667}
16668
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016669sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016670{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016671 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016672 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016673 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016674 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016675 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16676 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016677 next;
16678 }
16679 $Report .= " <symbol name=\"$Symbol\">\n";
16680 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016681 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016682 {
16683 if(defined $CompleteSignature{1}{$Symbol}
16684 and defined $CompleteSignature{1}{$Symbol}{"Header"})
16685 {
16686 $P1 = get_XmlSign($Symbol, 1);
16687 $S1 = get_Signature($Symbol, 1);
16688 }
16689 elsif($Symbol=~/\A(_Z|\?)/) {
16690 $S1 = $tr_name{$Symbol};
16691 }
16692 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016693 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016694 {
16695 if(defined $CompleteSignature{2}{$Symbol}
16696 and defined $CompleteSignature{2}{$Symbol}{"Header"})
16697 {
16698 $P2 = get_XmlSign($Symbol, 2);
16699 $S2 = get_Signature($Symbol, 2);
16700 }
16701 elsif($Symbol=~/\A(_Z|\?)/) {
16702 $S2 = $tr_name{$Symbol};
16703 }
16704 }
16705 if($S1)
16706 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016707 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016708 $Report .= $P1;
16709 $Report .= " </old>\n";
16710 }
16711 if($S2 and $S2 ne $S1)
16712 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016713 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016714 $Report .= $P2;
16715 $Report .= " </new>\n";
16716 }
16717 $Report .= " </symbol>\n";
16718 }
16719 $Report .= "</symbols_info>\n";
16720 return $Report;
16721}
16722
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016723sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016724{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016725 my ($Level, $Report) = @_;
16726 if($ReportFormat eq "xml") {
16727 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016728 }
16729 if($StdOut)
16730 { # --stdout option
16731 print STDOUT $Report;
16732 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016733 else
16734 {
16735 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016736 mkpath(get_dirname($RPath));
16737
16738 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
16739 print REPORT $Report;
16740 close(REPORT);
16741
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016742 if($Browse or $OpenReport)
16743 { # open in browser
16744 openReport($RPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016745 if($JoinReport or $DoubleReport)
16746 {
16747 if($Level eq "Binary")
16748 { # wait to open a browser
16749 sleep(1);
16750 }
16751 }
16752 }
16753 }
16754}
16755
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016756sub openReport($)
16757{
16758 my $Path = $_[0];
16759 my $Cmd = "";
16760 if($Browse)
16761 { # user-defined browser
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016762 $Cmd = $Browse." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016763 }
16764 if(not $Cmd)
16765 { # default browser
16766 if($OSgroup eq "macos") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040016767 $Cmd = "open \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016768 }
16769 elsif($OSgroup eq "windows") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040016770 $Cmd = "start ".path_format($Path, $OSgroup);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016771 }
16772 else
16773 { # linux, freebsd, solaris
16774 my @Browsers = (
16775 "x-www-browser",
16776 "sensible-browser",
16777 "firefox",
16778 "opera",
16779 "xdg-open",
16780 "lynx",
16781 "links"
16782 );
16783 foreach my $Br (@Browsers)
16784 {
16785 if($Br = get_CmdPath($Br))
16786 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040016787 $Cmd = $Br." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016788 last;
16789 }
16790 }
16791 }
16792 }
16793 if($Cmd)
16794 {
16795 if($Debug) {
16796 printMsg("INFO", "running $Cmd");
16797 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040016798 if($OSgroup ne "windows"
16799 and $OSgroup ne "macos")
16800 {
16801 if($Cmd!~/lynx|links/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016802 $Cmd .= " >\"/dev/null\" 2>&1 &";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040016803 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016804 }
16805 system($Cmd);
16806 }
16807 else {
16808 printMsg("ERROR", "cannot open report in browser");
16809 }
16810}
16811
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016812sub getReport($)
16813{
16814 my $Level = $_[0];
16815 if($ReportFormat eq "xml")
16816 { # XML
16817
16818 if($Level eq "Join")
16819 {
16820 my $Report = "<reports>\n";
16821 $Report .= getReport("Binary");
16822 $Report .= getReport("Source");
16823 $Report .= "</reports>\n";
16824 return $Report;
16825 }
16826 else
16827 {
16828 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
16829 my ($Summary, $MetaData) = get_Summary($Level);
16830 $Report .= $Summary."\n";
16831 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
16832 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
16833 $Report .= get_Report_SymbolsInfo($Level);
16834 $Report .= "</report>\n";
16835 return $Report;
16836 }
16837 }
16838 else
16839 { # HTML
16840 my $CssStyles = readModule("Styles", "Report.css");
16841 my $JScripts = readModule("Scripts", "Sections.js");
16842 if($Level eq "Join")
16843 {
16844 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
16845 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040016846 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
16847 my $Keywords = $TargetLibraryFName.", compatibility, API, report";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016848 my $Description = "Compatibility report for the $TargetLibraryFName $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
16849 my ($BSummary, $BMetaData) = get_Summary("Binary");
16850 my ($SSummary, $SMetaData) = get_Summary("Source");
16851 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>";
16852 $Report .= get_Report_Header("Join")."
16853 <br/><div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016854 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
16855 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016856 </div>";
16857 $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>";
16858 $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 +040016859 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016860 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
16861 return $Report;
16862 }
16863 else
16864 {
16865 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040016866 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
16867 my $Keywords = $TargetLibraryFName.", ".lc($Level)." compatibility, API, report";
16868 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 +040016869 if($Level eq "Binary")
16870 {
16871 if(getArch(1) eq getArch(2)
16872 and getArch(1) ne "unknown") {
16873 $Description .= " on ".showArch(getArch(1));
16874 }
16875 }
16876 my $Report = "<!-\- $MetaData -\->\n".composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."\n<body>\n<div><a name='Top'></a>\n";
16877 $Report .= get_Report_Header($Level)."\n".$Summary."\n";
16878 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
16879 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
16880 $Report .= get_SourceInfo();
16881 $Report .= "</div>\n<br/><br/><br/><hr/>\n";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016882 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016883 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
16884 return $Report;
16885 }
16886 }
16887}
16888
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016889sub getLegend()
16890{
16891 return "<br/>
16892<table class='summary'>
16893<tr>
16894 <td class='new'>added</td>
16895 <td class='passed'>compatible</td>
16896</tr>
16897<tr>
16898 <td class='warning'>warning</td>
16899 <td class='failed'>incompatible</td>
16900</tr></table>\n";
16901}
16902
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016903sub createReport()
16904{
16905 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016906 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016907 writeReport("Join", getReport("Join"));
16908 }
16909 elsif($DoubleReport)
16910 { # default
16911 writeReport("Binary", getReport("Binary"));
16912 writeReport("Source", getReport("Source"));
16913 }
16914 elsif($BinaryOnly)
16915 { # --binary
16916 writeReport("Binary", getReport("Binary"));
16917 }
16918 elsif($SourceOnly)
16919 { # --source
16920 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016921 }
16922}
16923
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016924sub getReportFooter($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016925{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016926 my ($LibName, $Wide) = @_;
16927 my $FooterStyle = $Wide?"width:99%":"width:97%;padding-top:3px";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016928 my $Footer = "<div style='$FooterStyle;font-size:11px;' align='right'><i>Generated on ".(localtime time); # report date
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016929 $Footer .= " for <span style='font-weight:bold'>$LibName</span>"; # tested library/system name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016930 $Footer .= " by <a href='".$HomePage{"Wiki"}."'>ABI Compliance Checker</a>"; # tool name
16931 my $ToolSummary = "<br/>A tool for checking backward compatibility of a C/C++ library API&#160;&#160;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016932 $Footer .= " $TOOL_VERSION &#160;$ToolSummary</i></div>"; # tool version
16933 return $Footer;
16934}
16935
16936sub get_Report_Problems($$)
16937{
16938 my ($Priority, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016939 my $Report = get_Report_TypeProblems($Priority, $Level);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016940 if(my $SProblems = get_Report_SymbolProblems($Priority, $Level)) {
16941 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016942 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016943 if($Priority eq "Low")
16944 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016945 $Report .= get_Report_ChangedConstants("Low", $Level);
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +040016946 if($ReportFormat eq "html")
16947 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016948 if($CheckImpl and $Level eq "Binary") {
16949 $Report .= get_Report_Impl();
16950 }
16951 }
16952 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016953 if($Priority eq "Safe")
16954 {
16955 $Report .= get_Report_ChangedConstants("Safe", $Level);
16956 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016957 if($ReportFormat eq "html")
16958 {
16959 if($Report)
16960 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016961 if($JoinReport)
16962 {
16963 if($Priority eq "Safe") {
16964 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
16965 }
16966 else {
16967 $Report = "<a name=\'".$Priority."_Risk_".$Level."_Problems\'></a>".$Report;
16968 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016969 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016970 else
16971 {
16972 if($Priority eq "Safe") {
16973 $Report = "<a name=\'Other_Changes\'></a>".$Report;
16974 }
16975 else {
16976 $Report = "<a name=\'".$Priority."_Risk_Problems\'></a>".$Report;
16977 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016978 }
16979 }
16980 }
16981 return $Report;
16982}
16983
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016984sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016985{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016986 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
16987 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
16988 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
16989 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016990 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
16991 <meta name=\"keywords\" content=\"$Keywords\" />
16992 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016993 <title>
16994 $Title
16995 </title>
16996 <style type=\"text/css\">
16997 $Styles
16998 </style>
16999 <script type=\"text/javascript\" language=\"JavaScript\">
17000 <!--
17001 $Scripts
17002 -->
17003 </script>
17004 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017005}
17006
17007sub insertIDs($)
17008{
17009 my $Text = $_[0];
17010 while($Text=~/CONTENT_ID/)
17011 {
17012 if(int($Content_Counter)%2) {
17013 $ContentID -= 1;
17014 }
17015 $Text=~s/CONTENT_ID/c_$ContentID/;
17016 $ContentID += 1;
17017 $Content_Counter += 1;
17018 }
17019 return $Text;
17020}
17021
17022sub checkPreprocessedUnit($)
17023{
17024 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017025 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017026 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017027 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017028
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017029 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017030 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017031 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017032 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017033 chomp($Line);
17034 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017035 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017036 $CurHeader = path_format($1, $OSgroup);
17037 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017038 $CurClass = "";
17039
17040 if(index($CurHeader, $TMP_DIR)==0) {
17041 next;
17042 }
17043
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017044 if(substr($CurHeaderName, 0, 1) eq "<")
17045 { # <built-in>, <command-line>, etc.
17046 $CurHeaderName = "";
17047 $CurHeader = "";
17048 }
17049
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017050 if($ExtraInfo)
17051 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017052 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017053 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17054 }
17055 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017056 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017057 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017058 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017059 if($CurHeaderName)
17060 {
17061 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17062 and not $Registered_Headers{$Version}{$CurHeader})
17063 { # not a target
17064 next;
17065 }
17066 if(not is_target_header($CurHeaderName, 1)
17067 and not is_target_header($CurHeaderName, 2))
17068 { # user-defined header
17069 next;
17070 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017071 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017072 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017073
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017074 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017075 {
17076 my ($Name, $Value) = ($1, $2);
17077 if(not $Constants{$Version}{$Name}{"Access"})
17078 {
17079 $Constants{$Version}{$Name}{"Access"} = "public";
17080 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017081 if($CurHeaderName) {
17082 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17083 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017084 }
17085 }
17086 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17087 $Constants{$Version}{$1}{"Access"} = "private";
17088 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017089 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017090 else
17091 {
17092 if(defined $ExtraDump)
17093 {
17094 if($Line=~/(\w+)\s*\(/)
17095 { # functions
17096 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17097 }
17098 #elsif($Line=~/(\w+)\s*;/)
17099 #{ # data
17100 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17101 #}
17102 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17103 $CurClass = $2;
17104 }
17105 }
17106 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017107 }
17108 close(PREPROC);
17109 foreach my $Constant (keys(%{$Constants{$Version}}))
17110 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017111 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17112 {
17113 delete($Constants{$Version}{$Constant});
17114 next;
17115 }
17116 if(not $ExtraDump and ($Constant=~/_h\Z/i or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
17117 { # skip
17118 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017119 }
17120 else {
17121 delete($Constants{$Version}{$Constant}{"Access"});
17122 }
17123 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017124 if($Debug)
17125 {
17126 mkpath($DEBUG_PATH{$Version});
17127 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17128 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017129}
17130
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017131sub uncoverConstant($$)
17132{
17133 my ($LibVersion, $Constant) = @_;
17134 return "" if(not $LibVersion or not $Constant);
17135 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17136 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17137 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17138 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017139
17140 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017141 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017142 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17143 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017144 {
17145 push(@RecurConstant, $Constant);
17146 my $Uncovered = uncoverConstant($LibVersion, $Value);
17147 if($Uncovered ne "") {
17148 $Value = $Uncovered;
17149 }
17150 pop(@RecurConstant);
17151 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017152
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017153 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017154 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017155 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17156 }
17157 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17158}
17159
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017160sub simpleConstant($$)
17161{
17162 my ($LibVersion, $Value) = @_;
17163 if($Value=~/\W/)
17164 {
17165 my $Value_Copy = $Value;
17166 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
17167 {
17168 my $Word = $1;
17169 if($Value!~/$Word\s*\(/)
17170 {
17171 my $Val = uncoverConstant($LibVersion, $Word);
17172 if($Val ne "")
17173 {
17174 $Value=~s/\b$Word\b/$Val/g;
17175 }
17176 }
17177 }
17178 }
17179 return $Value;
17180}
17181
17182sub computeValue($)
17183{
17184 my $Value = $_[0];
17185
17186 if($Value=~/\A\((-?[\d]+)\)\Z/) {
17187 return $1;
17188 }
17189
17190 if($Value=~/\A[\d\-\+()]+\Z/) {
17191 return eval($Value);
17192 }
17193
17194 return $Value;
17195}
17196
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017197my %IgnoreConstant = map {$_=>1} (
17198 "VERSION",
17199 "VERSIONCODE",
17200 "VERNUM",
17201 "VERS_INFO",
17202 "PATCHLEVEL",
17203 "INSTALLPREFIX",
17204 "VBUILD",
17205 "VPATCH",
17206 "VMINOR",
17207 "BUILD_STRING",
17208 "BUILD_TIME",
17209 "PACKAGE_STRING",
17210 "PRODUCTION",
17211 "CONFIGURE_COMMAND",
17212 "INSTALLDIR",
17213 "BINDIR",
17214 "CONFIG_FILE_PATH",
17215 "DATADIR",
17216 "EXTENSION_DIR",
17217 "INCLUDE_PATH",
17218 "LIBDIR",
17219 "LOCALSTATEDIR",
17220 "SBINDIR",
17221 "SYSCONFDIR",
17222 "RELEASE",
17223 "SOURCE_ID",
17224 "SUBMINOR",
17225 "MINOR",
17226 "MINNOR",
17227 "MINORVERSION",
17228 "MAJOR",
17229 "MAJORVERSION",
17230 "MICRO",
17231 "MICROVERSION",
17232 "BINARY_AGE",
17233 "INTERFACE_AGE",
17234 "CORE_ABI",
17235 "PATCH",
17236 "COPYRIGHT",
17237 "TIMESTAMP",
17238 "REVISION",
17239 "PACKAGE_TAG",
17240 "PACKAGEDATE",
17241 "NUMVERSION",
17242 "Release",
17243 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017244);
17245
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017246sub constantFilter($$$)
17247{
17248 my ($Name, $Value, $Level) = @_;
17249
17250 if($Level eq "Binary")
17251 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017252 if($Name=~/_t\Z/)
17253 { # __malloc_ptr_t
17254 return 1;
17255 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017256 foreach (keys(%IgnoreConstant))
17257 {
17258 if($Name=~/(\A|_)$_(_|\Z)/)
17259 { # version
17260 return 1;
17261 }
17262 if(/\A[A-Z].*[a-z]\Z/)
17263 {
17264 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
17265 { # version
17266 return 1;
17267 }
17268 }
17269 }
17270 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
17271 { # version
17272 return 1;
17273 }
17274 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
17275 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
17276 return 1;
17277 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017278
17279 if($Value=~/\A["'].*['"]/i)
17280 { # string
17281 return 0;
17282 }
17283
17284 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
17285 { # static int gcry_pth_init
17286 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017287 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017288 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017289 return 1;
17290 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017291 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017292 { # foo(p)
17293 return 1;
17294 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017295 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017296 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017297 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017298 return 1;
17299 }
17300 }
17301
17302 return 0;
17303}
17304
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017305sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017306{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017307 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017308 foreach my $Constant (keys(%{$Constants{1}}))
17309 {
17310 if($SkipConstants{1}{$Constant})
17311 { # skipped by the user
17312 next;
17313 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017314
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017315 if(my $Header = $Constants{1}{$Constant}{"Header"})
17316 {
17317 if(not is_target_header($Header, 1)
17318 and not is_target_header($Header, 2))
17319 { # user-defined header
17320 next;
17321 }
17322 }
17323 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017324 next;
17325 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017326
17327 my $Old_Value = uncoverConstant(1, $Constant);
17328
17329 if(constantFilter($Constant, $Old_Value, $Level))
17330 { # separate binary and source problems
17331 next;
17332 }
17333
17334 if(not defined $Constants{2}{$Constant}{"Value"})
17335 { # removed
17336 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
17337 "Target"=>$Constant,
17338 "Old_Value"=>$Old_Value );
17339 next;
17340 }
17341
17342 if($Constants{2}{$Constant}{"Value"} eq "")
17343 { # empty value
17344 # TODO: implement a rule
17345 next;
17346 }
17347
17348 my $New_Value = uncoverConstant(2, $Constant);
17349
17350 my $Old_Value_Pure = $Old_Value;
17351 my $New_Value_Pure = $New_Value;
17352
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017353 $Old_Value_Pure=~s/(\W)\s+/$1/g;
17354 $Old_Value_Pure=~s/\s+(\W)/$1/g;
17355 $New_Value_Pure=~s/(\W)\s+/$1/g;
17356 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017357
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017358 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017359
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017360 if($New_Value_Pure ne $Old_Value_Pure)
17361 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017362 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
17363 { # complex values
17364 next;
17365 }
17366 if(computeValue($Old_Value) eq computeValue($New_Value))
17367 { # expressions
17368 next;
17369 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017370 if(convert_integer($Old_Value) eq convert_integer($New_Value))
17371 { # 0x0001 and 0x1, 0x1 and 1 equal constants
17372 next;
17373 }
17374 if($Old_Value eq "0" and $New_Value eq "NULL")
17375 { # 0 => NULL
17376 next;
17377 }
17378 if($Old_Value eq "NULL" and $New_Value eq "0")
17379 { # NULL => 0
17380 next;
17381 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017382 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017383 "Target"=>$Constant,
17384 "Old_Value"=>$Old_Value,
17385 "New_Value"=>$New_Value );
17386 }
17387 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017388
17389 foreach my $Constant (keys(%{$Constants{2}}))
17390 {
17391 if(not defined $Constants{1}{$Constant}{"Value"})
17392 {
17393 if($SkipConstants{2}{$Constant})
17394 { # skipped by the user
17395 next;
17396 }
17397
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017398 if(my $Header = $Constants{2}{$Constant}{"Header"})
17399 {
17400 if(not is_target_header($Header, 1)
17401 and not is_target_header($Header, 2))
17402 { # user-defined header
17403 next;
17404 }
17405 }
17406 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017407 next;
17408 }
17409
17410 my $New_Value = uncoverConstant(2, $Constant);
17411 if(not defined $New_Value or $New_Value eq "") {
17412 next;
17413 }
17414
17415 if(constantFilter($Constant, $New_Value, $Level))
17416 { # separate binary and source problems
17417 next;
17418 }
17419
17420 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
17421 "Target"=>$Constant,
17422 "New_Value"=>$New_Value );
17423 }
17424 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017425}
17426
17427sub convert_integer($)
17428{
17429 my $Value = $_[0];
17430 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017431 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017432 return hex($Value);
17433 }
17434 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017435 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017436 return oct($Value);
17437 }
17438 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017439 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017440 return oct($Value);
17441 }
17442 else {
17443 return $Value;
17444 }
17445}
17446
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017447sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017448{
17449 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017450 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017451 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017452 {
17453 if($LibVersion==1)
17454 {
17455 printMsg("WARNING", "checking headers only");
17456 $CheckHeadersOnly = 1;
17457 }
17458 else {
17459 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
17460 }
17461 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017462
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017463 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017464 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017465 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017466
17467 if($CheckUndefined)
17468 {
17469 my %UndefinedLibs = ();
17470
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017471 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
17472
17473 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017474 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017475 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017476 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017477 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017478 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017479 if($Symbol_Library{$LibVersion}{$Symbol}
17480 or $DepSymbol_Library{$LibVersion}{$Symbol})
17481 { # exported by target library
17482 next;
17483 }
17484 if(index($Symbol, '@')!=-1)
17485 { # exported default symbol version (@@)
17486 $Symbol=~s/\@/\@\@/;
17487 if($Symbol_Library{$LibVersion}{$Symbol}
17488 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
17489 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017490 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017491 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017492 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
17493 $UndefinedLibs{$Path} = 1;
17494 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017495 }
17496 }
17497 }
17498 if($ExtraInfo)
17499 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017500 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017501 {
17502 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017503 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017504 foreach (@Paths)
17505 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017506 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017507 my ($Dir, $Name) = separate_path($_);
17508
17509 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017510 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017511 }
17512
17513 $Name = parse_libname($Name, "name", $OStarget);
17514 $Name=~s/\Alib//;
17515
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017516 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017517 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017518
17519 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
17520 {
17521 $LibString = " -L".esc($Dir).$LibString;
17522 }
17523
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017524 writeFile($ExtraInfo."/libs-string", $LibString);
17525 }
17526 }
17527 }
17528
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017529 if($ExtraInfo) {
17530 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
17531 }
17532
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017533 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017534 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017535 if($#LibPaths!=-1)
17536 {
17537 if(not keys(%{$Symbol_Library{$LibVersion}}))
17538 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017539 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017540 printMsg("WARNING", "checking headers only");
17541 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017542 }
17543 }
17544 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017545
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017546 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017547 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017548}
17549
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017550my %Prefix_Lib_Map=(
17551 # symbols for autodetecting library dependencies (by prefix)
17552 "pthread_" => ["libpthread"],
17553 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
17554 "cairo_" => ["libcairo"],
17555 "gtk_" => ["libgtk-x11-2.0"],
17556 "atk_" => ["libatk-1.0"],
17557 "gdk_" => ["libgdk-x11-2.0"],
17558 "gl" => ["libGL"],
17559 "glu" => ["libGLU"],
17560 "popt" => ["libpopt"],
17561 "Py" => ["libpython"],
17562 "jpeg_" => ["libjpeg"],
17563 "BZ2_" => ["libbz2"],
17564 "Fc" => ["libfontconfig"],
17565 "Xft" => ["libXft"],
17566 "SSL_" => ["libssl"],
17567 "sem_" => ["libpthread"],
17568 "snd_" => ["libasound"],
17569 "art_" => ["libart_lgpl_2"],
17570 "dbus_g" => ["libdbus-glib-1"],
17571 "GOMP_" => ["libgomp"],
17572 "omp_" => ["libgomp"],
17573 "cms" => ["liblcms"]
17574);
17575
17576my %Pattern_Lib_Map=(
17577 "SL[a-z]" => ["libslang"]
17578);
17579
17580my %Symbol_Lib_Map=(
17581 # symbols for autodetecting library dependencies (by name)
17582 "pow" => "libm",
17583 "fmod" => "libm",
17584 "sin" => "libm",
17585 "floor" => "libm",
17586 "cos" => "libm",
17587 "dlopen" => "libdl",
17588 "deflate" => "libz",
17589 "inflate" => "libz",
17590 "move_panel" => "libpanel",
17591 "XOpenDisplay" => "libX11",
17592 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017593 "clock_gettime" => "librt",
17594 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017595);
17596
17597sub find_SymbolLibs($$)
17598{
17599 my ($LibVersion, $Symbol) = @_;
17600
17601 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
17602 { # debug symbols
17603 return ();
17604 }
17605
17606 my %Paths = ();
17607
17608 if(my $LibName = $Symbol_Lib_Map{$Symbol})
17609 {
17610 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
17611 $Paths{$Path} = 1;
17612 }
17613 }
17614
17615 if(my $SymbolPrefix = getPrefix($Symbol))
17616 {
17617 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
17618 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
17619 }
17620
17621 if(not keys(%Paths))
17622 {
17623 if(defined $Prefix_Lib_Map{$SymbolPrefix})
17624 {
17625 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
17626 {
17627 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
17628 $Paths{$Path} = 1;
17629 }
17630 }
17631 }
17632 }
17633
17634 if(not keys(%Paths))
17635 {
17636 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
17637 {
17638 if($Symbol=~/\A$Prefix/)
17639 {
17640 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
17641 {
17642 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
17643 $Paths{$Path} = 1;
17644 }
17645 }
17646 }
17647 }
17648 }
17649
17650 if(not keys(%Paths))
17651 {
17652 if($SymbolPrefix)
17653 { # try to find a library by symbol prefix
17654 if($SymbolPrefix eq "inotify" and
17655 index($Symbol, "\@GLIBC")!=-1)
17656 {
17657 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
17658 $Paths{$Path} = 1;
17659 }
17660 }
17661 else
17662 {
17663 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
17664 $Paths{$Path} = 1;
17665 }
17666 }
17667 }
17668 }
17669
17670 if(my @Paths = keys(%Paths)) {
17671 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
17672 }
17673 }
17674 return keys(%Paths);
17675}
17676
17677sub get_LibPath_Prefix($$)
17678{
17679 my ($LibVersion, $Prefix) = @_;
17680
17681 $Prefix = lc($Prefix);
17682 $Prefix=~s/[_]+\Z//g;
17683
17684 foreach ("-2", "2", "-1", "1", "")
17685 { # libgnome-2.so
17686 # libxml2.so
17687 # libdbus-1.so
17688 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
17689 return $Path;
17690 }
17691 }
17692 return "";
17693}
17694
17695sub getPrefix($)
17696{
17697 my $Str = $_[0];
17698 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
17699 { # XmuValidArea: Xmu
17700 return $1;
17701 }
17702 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
17703 { # snfReadFont: snf
17704 return $1;
17705 }
17706 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
17707 { # XRRTimes: XRR
17708 return $1;
17709 }
17710 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
17711 { # H5HF_delete: H5
17712 return $1;
17713 }
17714 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
17715 { # alarm_event_add: alarm_
17716 return $1;
17717 }
17718 elsif($Str=~/\A(([a-z])\2{1,})/i)
17719 { # ffopen
17720 return $1;
17721 }
17722 return "";
17723}
17724
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017725sub getSymbolSize($$)
17726{ # size from the shared library
17727 my ($Symbol, $LibVersion) = @_;
17728 return 0 if(not $Symbol);
17729 if(defined $Symbol_Library{$LibVersion}{$Symbol}
17730 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
17731 {
17732 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
17733 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
17734 {
17735 if($Size<0) {
17736 return -$Size;
17737 }
17738 }
17739 }
17740 return 0;
17741}
17742
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017743sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017744{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
17745 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017746 my ($Name, $Type) = @_;
17747
17748 # single
17749 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017750 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017751 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017752 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017753 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017754
17755 # double
17756 if($Name=~/$DEFAULT_STD_PARMS/)
17757 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040017758 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017759 {
17760 my ($ShortName, $FuncParams) = split_Signature($Name);
17761
17762 foreach my $FParam (separate_Params($FuncParams, 0, 0))
17763 {
17764 if(index($FParam, "<")!=-1)
17765 {
17766 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
17767 my $FParam_N = canonifyName($FParam, "T");
17768 if($FParam_N ne $FParam) {
17769 $Name=~s/\Q$FParam\E/$FParam_N/g;
17770 }
17771 }
17772 }
17773 }
17774 elsif($Type eq "T")
17775 {
17776 my ($ShortTmpl, $TmplParams) = template_Base($Name);
17777
17778 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040017779 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017780 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040017781 my $FParam = $TParams[0];
17782 foreach my $Pos (1 .. $#TParams)
17783 {
17784 my $TParam = $TParams[$Pos];
17785 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
17786 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
17787 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017788 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017789 }
17790 }
17791 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040017792 if($Type eq "S") {
17793 return formatName($Name, "S");
17794 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017795 return $Name;
17796}
17797
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017798sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017799{
17800 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017801 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017802 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017803 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017804 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017805 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017806 next if($tr_name{$Symbol});
17807 $Symbol=~s/[\@\$]+(.*)\Z//;
17808 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017809 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040017810 elsif(index($Symbol, "?")==0)
17811 {
17812 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017813 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017814 }
17815 else
17816 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017817 $tr_name{$Symbol} = $Symbol;
17818 $mangled_name_gcc{$Symbol} = $Symbol;
17819 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017820 }
17821 }
17822 if($#MnglNames1 > -1)
17823 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017824 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017825 foreach my $MnglName (@MnglNames1)
17826 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017827 if(my $Unmangled = pop(@UnmangledNames))
17828 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040017829 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017830 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
17831 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
17832 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017833 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017834 and $tr_name{$MnglName}=~/vtable for (.+)/)
17835 { # bind class name and v-table symbol
17836 my $ClassName = $1;
17837 $ClassVTable{$ClassName} = $MnglName;
17838 $VTableClass{$MnglName} = $ClassName;
17839 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017840 }
17841 }
17842 }
17843 if($#MnglNames2 > -1)
17844 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017845 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017846 foreach my $MnglName (@MnglNames2)
17847 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017848 if(my $Unmangled = pop(@UnmangledNames))
17849 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017850 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017851 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
17852 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017853 }
17854 }
17855 return \%tr_name;
17856}
17857
17858sub link_symbol($$$)
17859{
17860 my ($Symbol, $RunWith, $Deps) = @_;
17861 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
17862 return 1;
17863 }
17864 if($Deps eq "+Deps")
17865 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017866 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017867 return 1;
17868 }
17869 }
17870 return 0;
17871}
17872
17873sub link_symbol_internal($$$)
17874{
17875 my ($Symbol, $RunWith, $Where) = @_;
17876 return 0 if(not $Where or not $Symbol);
17877 if($Where->{$RunWith}{$Symbol})
17878 { # the exact match by symbol name
17879 return 1;
17880 }
17881 if(my $VSym = $SymVer{$RunWith}{$Symbol})
17882 { # indirect symbol version, i.e.
17883 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017884 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017885 if($Where->{$RunWith}{$VSym}) {
17886 return 1;
17887 }
17888 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017889 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017890 if($Sym and $Ver)
17891 { # search for the symbol with the same version
17892 # or without version
17893 if($Where->{$RunWith}{$Sym})
17894 { # old: foo@v|foo@@v
17895 # new: foo
17896 return 1;
17897 }
17898 if($Where->{$RunWith}{$Sym."\@".$Ver})
17899 { # old: foo|foo@@v
17900 # new: foo@v
17901 return 1;
17902 }
17903 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
17904 { # old: foo|foo@v
17905 # new: foo@@v
17906 return 1;
17907 }
17908 }
17909 return 0;
17910}
17911
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017912sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017913{
17914 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017915 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017916 my @Imported = ();
17917 if($OSgroup eq "macos")
17918 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017919 my $NM = get_CmdPath("nm");
17920 if(not $NM) {
17921 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017922 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017923 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017924 while(<APP>)
17925 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040017926 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017927 push(@Imported, $1);
17928 }
17929 }
17930 close(APP);
17931 }
17932 elsif($OSgroup eq "windows")
17933 {
17934 my $DumpBinCmd = get_CmdPath("dumpbin");
17935 if(not $DumpBinCmd) {
17936 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
17937 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017938 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017939 while(<APP>)
17940 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017941 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
17942 push(@Imported, $1);
17943 }
17944 }
17945 close(APP);
17946 }
17947 else
17948 {
17949 my $ReadelfCmd = get_CmdPath("readelf");
17950 if(not $ReadelfCmd) {
17951 exitStatus("Not_Found", "can't find \"readelf\"");
17952 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017953 open(APP, "$ReadelfCmd -WhlSsdA \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017954 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017955 while(<APP>)
17956 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017957 if(defined $symtab)
17958 { # do nothing with symtab
17959 if(index($_, "'.dynsym'")!=-1)
17960 { # dynamic table
17961 $symtab = undef;
17962 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017963 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017964 elsif(index($_, "'.symtab'")!=-1)
17965 { # symbol table
17966 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017967 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017968 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017969 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017970 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
17971 if($Ndx eq "UND")
17972 { # only imported symbols
17973 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017974 }
17975 }
17976 }
17977 close(APP);
17978 }
17979 return @Imported;
17980}
17981
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017982my %ELF_BIND = map {$_=>1} (
17983 "WEAK",
17984 "GLOBAL"
17985);
17986
17987my %ELF_TYPE = map {$_=>1} (
17988 "FUNC",
17989 "IFUNC",
17990 "OBJECT",
17991 "COMMON"
17992);
17993
17994my %ELF_VIS = map {$_=>1} (
17995 "DEFAULT",
17996 "PROTECTED"
17997);
17998
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017999sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018000{ # read the line of 'readelf' output corresponding to the symbol
18001 my @Info = split(/\s+/, $_[0]);
18002 # Num: Value Size Type Bind Vis Ndx Name
18003 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018004 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018005 shift(@Info); # spaces
18006 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018007
18008 if($#Info==7)
18009 { # UND SYMBOL (N)
18010 if($Info[7]=~/\(\d+\)/) {
18011 pop(@Info);
18012 }
18013 }
18014
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018015 if($#Info!=6)
18016 { # other lines
18017 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018018 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018019 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018020 return () if(not defined $ELF_BIND{$Info[3]});
18021 return () if(not defined $ELF_VIS{$Info[4]});
18022 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18023 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18024 return ();
18025 }
18026 if($OStarget eq "symbian")
18027 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18028 if(index($Info[6], "_._.absent_export_")!=-1)
18029 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18030 return ();
18031 }
18032 $Info[6]=~s/\@.+//g; # remove version
18033 }
18034 if(index($Info[2], "0x") == 0)
18035 { # size == 0x3d158
18036 $Info[2] = hex($Info[2]);
18037 }
18038 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018039}
18040
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018041sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018042{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018043 my ($LibVersion, $Name) = @_;
18044 return "" if(not $LibVersion or not $Name);
18045 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18046 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018047 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018048 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18049}
18050
18051sub get_LibPath_I($$)
18052{
18053 my ($LibVersion, $Name) = @_;
18054 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018055 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018056 if(-f $Name)
18057 { # absolute path
18058 return $Name;
18059 }
18060 else
18061 { # broken
18062 return "";
18063 }
18064 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018065 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018066 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018067 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018068 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018069 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018070 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018071 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018072 }
18073 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18074 { # ldconfig default paths
18075 return $DefaultPath;
18076 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018077 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018078 { # search in default linker directories
18079 # and then in all system paths
18080 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018081 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018082 }
18083 }
18084 detectSystemObjects() if(not keys(%SystemObjects));
18085 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18086 return $AllObjects[0];
18087 }
18088 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18089 {
18090 if($ShortName ne $Name)
18091 { # FIXME: check this case
18092 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18093 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018094 }
18095 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018096 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018097 # can't find
18098 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018099}
18100
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018101sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018102{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018103 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18104 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018105
18106 my $Real_Path = realpath($Lib_Path);
18107
18108 if(not $Real_Path)
18109 { # broken link
18110 return ();
18111 }
18112
18113 my $Lib_Name = get_filename($Real_Path);
18114
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018115 if($ExtraInfo)
18116 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018117 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018118 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018119 }
18120
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018121 if($IsNeededLib)
18122 {
18123 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18124 return ();
18125 }
18126 }
18127 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018128 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018129
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018130 if($CheckImpl)
18131 {
18132 if(not $IsNeededLib) {
18133 getImplementations($LibVersion, $Lib_Path);
18134 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018135 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018136
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018137 push(@RecurLib, $Lib_Name);
18138 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018139 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18140
18141 if(not $IsNeededLib)
18142 { # special cases: libstdc++ and libc
18143 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18144 {
18145 if($ShortName eq "libstdc++")
18146 { # libstdc++.so.6
18147 $STDCXX_TESTING = 1;
18148 }
18149 elsif($ShortName eq "libc")
18150 { # libc-2.11.3.so
18151 $GLIBC_TESTING = 1;
18152 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018153 }
18154 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018155 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018156 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018157 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018158 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018159 mkpath(get_dirname($DebugPath));
18160 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018161 if($OStarget eq "macos")
18162 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018163 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018164 if(not $NM) {
18165 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018166 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018167 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018168 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018169 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018170 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018171 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018172 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018173 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018174 else
18175 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018176 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018177 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018178 while(<LIB>)
18179 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018180 if($CheckUndefined)
18181 {
18182 if(not $IsNeededLib)
18183 {
18184 if(/ U _([\w\$]+)\s*\Z/)
18185 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018186 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018187 next;
18188 }
18189 }
18190 }
18191
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018192 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018193 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018194 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018195 if($IsNeededLib)
18196 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018197 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018198 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018199 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18200 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018201 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018202 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018203 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018204 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018205 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18206 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018207 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18208 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018209 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018210 setLanguage($LibVersion, "C++");
18211 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018212 }
18213 if($CheckObjectsOnly
18214 and $LibVersion==1) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018215 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018216 }
18217 }
18218 }
18219 }
18220 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018221
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018222 if($Deps)
18223 {
18224 if($LIB_TYPE eq "dynamic")
18225 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018226
18227 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018228 if(not $OtoolCmd) {
18229 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018230 }
18231
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018232 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18233 while(<LIB>)
18234 {
18235 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
18236 and $1 ne $Lib_Path) {
18237 $NeededLib{$1} = 1;
18238 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018239 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018240 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018241 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018242 }
18243 }
18244 elsif($OStarget eq "windows")
18245 { # Windows *.dll, *.lib
18246 my $DumpBinCmd = get_CmdPath("dumpbin");
18247 if(not $DumpBinCmd) {
18248 exitStatus("Not_Found", "can't find \"dumpbin\"");
18249 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018250 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018251 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018252 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018253 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018254 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018255 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018256 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018257 else
18258 { # write to pipe
18259 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018260 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018261 while(<LIB>)
18262 { # 1197 4AC 0000A620 SetThreadStackGuarantee
18263 # 1198 4AD SetThreadToken (forwarded to ...)
18264 # 3368 _o2i_ECPublicKey
18265 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*\Z/i
18266 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
18267 or /\A\s*\d+\s+_([\w\?\@]+)\s*\Z/)
18268 { # dynamic, static and forwarded symbols
18269 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018270 if($IsNeededLib)
18271 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018272 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018273 {
18274 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
18275 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
18276 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018277 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018278 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018279 {
18280 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
18281 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018282 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18283 {
18284 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
18285 setLanguage($LibVersion, "C++");
18286 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018287 }
18288 if($CheckObjectsOnly
18289 and $LibVersion==1) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018290 $CheckedSymbols{"Binary"}{$realname} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018291 }
18292 }
18293 }
18294 }
18295 close(LIB);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018296 if($Deps)
18297 {
18298 if($LIB_TYPE eq "dynamic")
18299 { # dependencies
18300 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18301 while(<LIB>)
18302 {
18303 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
18304 and $1 ne $Lib_Path) {
18305 $NeededLib{path_format($1, $OSgroup)} = 1;
18306 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018307 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018308 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018309 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018310 }
18311 }
18312 else
18313 { # Unix; *.so, *.a
18314 # Symbian: *.dso, *.lib
18315 my $ReadelfCmd = get_CmdPath("readelf");
18316 if(not $ReadelfCmd) {
18317 exitStatus("Not_Found", "can't find \"readelf\"");
18318 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018319 $ReadelfCmd .= " -WhlSsdA \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
18320 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018321 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018322 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018323 system($ReadelfCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018324 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018325 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018326 else
18327 { # write to pipe
18328 open(LIB, $ReadelfCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018329 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018330 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018331 while(<LIB>)
18332 {
18333 if($LIB_TYPE eq "dynamic")
18334 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018335 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018336 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018337 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018338 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018339 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018340 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018341 # do nothing with symtab
18342 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018343 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018344 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018345 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018346 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018347 next;
18348 }
18349 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018350 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018351 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018352 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018353 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018354 if($CheckUndefined)
18355 {
18356 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018357 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018358 }
18359 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018360 next;
18361 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040018362 if($Bind eq "WEAK")
18363 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018364 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040018365 if($Weak eq "-Weak")
18366 { # skip WEAK symbols
18367 next;
18368 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018369 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018370 my $Short = $Symbol;
18371 $Short=~s/\@.+//g;
18372 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018373 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018374 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
18375 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018376 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018377 if($IsNeededLib)
18378 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018379 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018380 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018381 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18382 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018383 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018384 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018385 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018386 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018387 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18388 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
18389 if($Vers)
18390 {
18391 if($LIB_EXT eq "so")
18392 { # value
18393 $Interface_Value{$LibVersion}{$Symbol} = $Value;
18394 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
18395 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018396 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018397 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18398 {
18399 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
18400 setLanguage($LibVersion, "C++");
18401 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018402 }
18403 if($CheckObjectsOnly
18404 and $LibVersion==1) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018405 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018406 }
18407 }
18408 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018409 elsif($LIB_TYPE eq "dynamic")
18410 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018411 if($Deps)
18412 {
18413 if(/NEEDED.+\[([^\[\]]+)\]/)
18414 { # dependencies:
18415 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
18416 $NeededLib{$1} = 1;
18417 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018418 }
18419 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018420 }
18421 close(LIB);
18422 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018423 if($Vers)
18424 {
18425 if(not $IsNeededLib and $LIB_EXT eq "so")
18426 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018427 my %Found = ();
18428
18429 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018430 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018431 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018432 next if(index($Symbol,"\@")==-1);
18433 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018434 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018435 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018436 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018437 if($Symbol_SameValue ne $Symbol
18438 and index($Symbol_SameValue,"\@")==-1)
18439 {
18440 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018441 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018442 last;
18443 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018444 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018445 }
18446 }
18447
18448 # default
18449 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
18450 {
18451 next if(defined $Found{$Symbol});
18452 next if(index($Symbol,"\@\@")==-1);
18453
18454 if($Symbol=~/\A([^\@]*)\@\@/
18455 and not $SymVer{$LibVersion}{$1})
18456 {
18457 $SymVer{$LibVersion}{$1} = $Symbol;
18458 $Found{$Symbol} = 1;
18459 }
18460 }
18461
18462 # non-default
18463 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
18464 {
18465 next if(defined $Found{$Symbol});
18466 next if(index($Symbol,"\@")==-1);
18467
18468 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
18469 and not $SymVer{$LibVersion}{$1})
18470 {
18471 $SymVer{$LibVersion}{$1} = $Symbol;
18472 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018473 }
18474 }
18475 }
18476 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018477 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018478 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018479 foreach my $DyLib (sort keys(%NeededLib))
18480 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018481 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
18482
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018483 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
18484 {
18485 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
18486 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
18487 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018488 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018489 }
18490 }
18491 pop(@RecurLib);
18492 return $Library_Symbol{$LibVersion};
18493}
18494
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018495sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018496{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018497 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018498 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018499 return keys(%Prefixes);
18500}
18501
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018502sub get_prefixes_I($$)
18503{
18504 foreach my $P (@{$_[0]})
18505 {
18506 my @Parts = reverse(split(/[\/\\]+/, $P));
18507 my $Name = $Parts[0];
18508 foreach (1 .. $#Parts)
18509 {
18510 $_[1]->{$Name}{$P} = 1;
18511 last if($_>4 or $Parts[$_] eq "include");
18512 $Name = $Parts[$_].$SLASH.$Name;
18513 }
18514 }
18515}
18516
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018517sub detectSystemHeaders()
18518{
18519 my @SysHeaders = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018520 foreach my $DevelPath (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018521 {
18522 next if(not -d $DevelPath);
18523 # search for all header files in the /usr/include
18524 # with or without extension (ncurses.h, QtCore, ...)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018525 push(@SysHeaders, cmd_find($DevelPath,"f"));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018526 foreach my $Link (cmd_find($DevelPath,"l"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018527 { # add symbolic links
18528 if(-f $Link) {
18529 push(@SysHeaders, $Link);
18530 }
18531 }
18532 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018533 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018534 { # search for config headers in the /usr/lib
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018535 next if(not -d $DevelPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018536 foreach (cmd_find($DevelPath,"f",'\.h(pp|xx)?\Z|\/include\/',"",1))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018537 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018538 if(/\/(gcc|jvm|syslinux|kbd|parrot|xemacs)/)
18539 { # skip useless headers
18540 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018541 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018542 push(@SysHeaders, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018543 }
18544 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018545 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018546}
18547
18548sub detectSystemObjects()
18549{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018550 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018551 {
18552 next if(not -d $DevelPath);
18553 foreach my $Path (find_libs($DevelPath,"",""))
18554 { # search for shared libraries in the /usr/lib (including symbolic links)
18555 $SystemObjects{parse_libname(get_filename($Path), "name+ext", $OStarget)}{$Path}=1;
18556 }
18557 }
18558}
18559
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018560sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018561{
18562 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018563 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018564 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
18565 {
18566 if(not -e $Dest) {
18567 exitStatus("Access_Error", "can't access \'$Dest\'");
18568 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018569 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018570 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
18571 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018572 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018573 }
18574 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018575 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018576}
18577
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018578sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018579{
18580 my ($Path, $LibVersion) = @_;
18581 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018582 my $Name = get_filename($Path);
18583 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018584 return 1;
18585 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018586 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018587 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
18588 return 1;
18589 }
18590 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
18591 {
18592 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
18593 return 1;
18594 }
18595 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018596 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018597 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018598 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018599 return 1;
18600 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018601 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018602 return 1;
18603 }
18604 }
18605 return 0;
18606}
18607
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018608sub specificHeader($$)
18609{
18610 my ($Header, $Spec) = @_;
18611 my $Name = get_filename($Header);
18612
18613 if($Spec eq "windows")
18614 {# MS Windows
18615 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
18616 return 1 if($Name=~/([._-]w|win)(32|64)/i);
18617 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
18618 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
18619 my @Dirs = (
18620 "win32",
18621 "win64",
18622 "win",
18623 "windows",
18624 "msvcrt"
18625 ); # /gsf-win32/
18626 if(my $DIRs = join("|", @Dirs)) {
18627 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
18628 }
18629 }
18630 elsif($Spec eq "macos")
18631 { # Mac OS
18632 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
18633 }
18634
18635 return 0;
18636}
18637
18638sub skipAlienHeader($)
18639{
18640 my $Path = $_[0];
18641 my $Name = get_filename($Path);
18642 my $Dir = get_dirname($Path);
18643
18644 if($Tolerance=~/2/)
18645 { # 2 - skip internal headers
18646 my @Terms = (
18647 "p",
18648 "priv",
18649 "int",
18650 "impl",
18651 "implementation",
18652 "internal",
18653 "private",
18654 "old",
18655 "compat",
18656 "debug",
18657 "test",
18658 "gen"
18659 );
18660
18661 my @Dirs = (
18662 "private",
18663 "priv",
18664 "port",
18665 "impl",
18666 "internal",
18667 "detail",
18668 "details",
18669 "old",
18670 "compat",
18671 "debug",
18672 "config",
18673 "compiler",
18674 "platform",
18675 "test"
18676 );
18677
18678 if(my $TERMs = join("|", @Terms)) {
18679 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
18680 }
18681 if(my $DIRs = join("|", @Dirs)) {
18682 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
18683 }
18684
18685 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
18686 }
18687
18688 if($Tolerance=~/1/)
18689 { # 1 - skip non-Linux headers
18690 if($OSgroup ne "windows")
18691 {
18692 if(specificHeader($Path, "windows")) {
18693 return 1;
18694 }
18695 }
18696 if($OSgroup ne "macos")
18697 {
18698 if(specificHeader($Path, "macos")) {
18699 return 1;
18700 }
18701 }
18702 }
18703
18704 # valid
18705 return 0;
18706}
18707
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018708sub skipHeader($$)
18709{
18710 my ($Path, $LibVersion) = @_;
18711 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018712 if(defined $Cache{"skipHeader"}{$Path}) {
18713 return $Cache{"skipHeader"}{$Path};
18714 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018715 if(defined $Tolerance and $Tolerance=~/1|2/)
18716 { # --tolerant
18717 if(skipAlienHeader($Path)) {
18718 return ($Cache{"skipHeader"}{$Path} = 1);
18719 }
18720 }
18721 if(not keys(%{$SkipHeaders{$LibVersion}})) {
18722 return 0;
18723 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018724 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
18725}
18726
18727sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018728{ # returns:
18729 # 1 - if header should NOT be included and checked
18730 # 2 - if header should NOT be included, but should be checked
18731 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018732 my $Name = get_filename($Path);
18733 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018734 return $Kind;
18735 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018736 foreach my $D (keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018737 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018738 if(index($Path, $D)!=-1)
18739 {
18740 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
18741 return $SkipHeaders{$LibVersion}{"Path"}{$D};
18742 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018743 }
18744 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018745 foreach my $P (keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018746 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018747 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
18748 {
18749 if($Name=~/$P/) {
18750 return $Kind;
18751 }
18752 if($P=~/[\/\\]/ and $Path=~/$P/) {
18753 return $Kind;
18754 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018755 }
18756 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018757
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018758 return 0;
18759}
18760
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018761sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018762{
18763 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018764 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018765 { # system directory
18766 return;
18767 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018768 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018769 { # already registered
18770 return;
18771 }
18772 foreach my $Path (find_libs($Dir,"",1))
18773 {
18774 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018775 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018776 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018777 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018778 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
18779}
18780
18781sub registerObject($$)
18782{
18783 my ($Path, $LibVersion) = @_;
18784 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018785 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko27681702012-11-12 16:33:39 +040018786 if($OSgroup=~/linux|bsd/i)
18787 {
18788 if(my $SONAME = getSONAME($Path)) {
18789 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
18790 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018791 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018792 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
18793 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018794 }
18795}
18796
18797sub getSONAME($)
18798{
18799 my $Path = $_[0];
18800 return if(not $Path);
18801 if(defined $Cache{"getSONAME"}{$Path}) {
18802 return $Cache{"getSONAME"}{$Path};
18803 }
18804 my $ObjdumpCmd = get_CmdPath("objdump");
18805 if(not $ObjdumpCmd) {
18806 exitStatus("Not_Found", "can't find \"objdump\"");
18807 }
18808 my $SonameCmd = "$ObjdumpCmd -x $Path 2>$TMP_DIR/null";
18809 if($OSgroup eq "windows") {
18810 $SonameCmd .= " | find \"SONAME\"";
18811 }
18812 else {
18813 $SonameCmd .= " | grep SONAME";
18814 }
18815 if(my $SonameInfo = `$SonameCmd`) {
18816 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
18817 return ($Cache{"getSONAME"}{$Path} = $1);
18818 }
18819 }
18820 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018821}
18822
18823sub getSOPaths_Dest($$)
18824{
18825 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018826 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018827 return ();
18828 }
18829 if(-f $Dest)
18830 {
18831 if(not parse_libname($Dest, "name", $OStarget)) {
18832 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
18833 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018834 registerObject($Dest, $LibVersion);
18835 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018836 return ($Dest);
18837 }
18838 elsif(-d $Dest)
18839 {
18840 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018841 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018842 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018843 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
18844 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018845 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018846 { # all files and symlinks that match the name of a library
18847 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
18848 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018849 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018850 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018851 }
18852 }
18853 }
18854 else
18855 { # search for all files and symlinks
18856 foreach my $Path (find_libs($Dest,"",""))
18857 {
18858 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018859 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018860 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018861 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018862 }
18863 if($OSgroup eq "macos")
18864 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018865 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018866 {
18867 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018868 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018869 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018870 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
18871 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018872 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018873 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018874 }
18875 }
18876 }
18877 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018878 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018879 }
18880 else {
18881 return ();
18882 }
18883}
18884
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018885sub isCyclical($$)
18886{
18887 my ($Stack, $Value) = @_;
18888 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018889}
18890
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018891sub detectWordSize()
18892{
18893 return "" if(not $GCC_PATH);
18894 if($Cache{"detectWordSize"}) {
18895 return $Cache{"detectWordSize"};
18896 }
18897 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018898 my $Defines = `$GCC_PATH -E -dD \"$TMP_DIR/empty.h\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018899 unlink("$TMP_DIR/empty.h");
18900 my $WSize = 0;
18901 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018902 { # GCC 4
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018903 $WSize = $1;
18904 }
18905 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018906 { # GCC 3
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018907 my $PTRDIFF = $1;
18908 if($PTRDIFF=~/long/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018909 $WSize = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018910 }
18911 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018912 $WSize = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018913 }
18914 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018915 if(not $WSize) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018916 exitStatus("Error", "can't check WORD size");
18917 }
18918 return ($Cache{"detectWordSize"} = $WSize);
18919}
18920
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040018921sub getWordSize($) {
18922 return $WORD_SIZE{$_[0]};
18923}
18924
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018925sub majorVersion($)
18926{
18927 my $V = $_[0];
18928 return 0 if(not $V);
18929 my @VParts = split(/\./, $V);
18930 return $VParts[0];
18931}
18932
18933sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018934{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018935 my ($V1, $V2) = @_;
18936 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018937 my @V1Parts = split(/\./, $V1);
18938 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018939 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
18940 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018941 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
18942 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
18943 }
18944 return -1 if($#V1Parts < $#V2Parts);
18945 return 1 if($#V1Parts > $#V2Parts);
18946 return 0;
18947}
18948
18949sub read_ABI_Dump($$)
18950{
18951 my ($LibVersion, $Path) = @_;
18952 return if(not $LibVersion or not -e $Path);
18953 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018954 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018955 { # input *.abi
18956 $FilePath = $Path;
18957 }
18958 else
18959 { # input *.abi.tar.gz
18960 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018961 if(not isDump_U($FilePath)) {
18962 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
18963 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018964 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018965
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018966 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040018967
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018968 my $Line = readLineNum($FilePath, 0);
18969 if($Line=~/xml/)
18970 { # XML format
18971 loadModule("XmlDump");
18972 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018973 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018974 else
18975 { # Perl Data::Dumper format (default)
18976 open(DUMP, $FilePath);
18977 local $/ = undef;
18978 my $Content = <DUMP>;
18979 close(DUMP);
18980
18981 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
18982 { # remove temp file
18983 unlink($FilePath);
18984 }
18985 if($Content!~/};\s*\Z/) {
18986 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
18987 }
18988 $ABI = eval($Content);
18989 if(not $ABI) {
18990 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
18991 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018992 }
18993 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018994 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040018995 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018996 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018997 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018998 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018999 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019000 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019001
19002 if($ABI->{"ABI_DUMP_VERSION"})
19003 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019004 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019005 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019006 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019007 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019008 }
19009 else
19010 { # support for old ABI dumps
19011 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019012 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019013 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019014 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019015 }
19016 if(majorVersion($DVersion)<2)
19017 { # support for old ABI dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019018 if($UseOldDumps)
19019 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019020 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)<0) {
19021 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (older than $OLDEST_SUPPORTED_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019022 }
19023 }
19024 else
19025 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019026 my $Msg = "incompatible version \'$DVersion\' of specified ABI dump (allowed only 2.0<=V<=$ABI_DUMP_VERSION)";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019027 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)>=0) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019028 $Msg .= "\nUse -old-dumps option to use old-version dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019029 }
19030 exitStatus("Dump_Version", $Msg);
19031 }
19032 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019033
19034 if(defined $ABI->{"ABI_DUMPER_VERSION"})
19035 { # DWARF ABI Dump
19036 $UseConv_Real{$LibVersion}{"P"} = 1;
19037 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19038
19039 $UsedDump{$LibVersion}{"DWARF"} = 1;
19040
19041 $TargetComponent = "module";
19042 }
19043
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019044 if(not checkDump($LibVersion, "2.11"))
19045 { # old ABI dumps
19046 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019047 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019048 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019049 { # ABI dump created with --binary option
19050 $UsedDump{$LibVersion}{"BinOnly"} = 1;
19051 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019052 else
19053 { # default
19054 $UsedDump{$LibVersion}{"SrcBin"} = 1;
19055 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019056
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019057 if(defined $ABI->{"Mode"}
19058 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019059 { # --ext option
19060 $ExtendedCheck = 1;
19061 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019062 if($ABI->{"Extra"}) {
19063 $ExtraDump = 1;
19064 }
19065
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019066 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019067 {
19068 $UsedDump{$LibVersion}{"L"} = $Lang;
19069 setLanguage($LibVersion, $Lang);
19070 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019071 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019072 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019073 }
19074 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019075 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019076 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019077 if(not $TInfo)
19078 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019079 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019080 }
19081 my %Tid_TDid = ();
19082 foreach my $TDid (keys(%{$TInfo}))
19083 {
19084 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
19085 {
19086 $MAX_ID = $Tid if($Tid>$MAX_ID);
19087 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
19088 $Tid_TDid{$Tid}{$TDid}=1;
19089 }
19090 }
19091 my %NewID = ();
19092 foreach my $Tid (keys(%Tid_TDid))
19093 {
19094 my @TDids = keys(%{$Tid_TDid{$Tid}});
19095 if($#TDids>=1)
19096 {
19097 foreach my $TDid (@TDids)
19098 {
19099 if($TDid) {
19100 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19101 }
19102 else
19103 {
19104 if(my $ID = ++$MAX_ID)
19105 {
19106 $NewID{$TDid}{$Tid} = $ID;
19107 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
19108 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
19109 }
19110 }
19111 }
19112 }
19113 else
19114 {
19115 my $TDid = $TDids[0];
19116 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19117 }
19118 }
19119 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
19120 {
19121 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
19122 if(defined $Info{"BaseType"})
19123 {
19124 my $Bid = $Info{"BaseType"}{"Tid"};
19125 my $BDid = $Info{"BaseType"}{"TDid"};
19126 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019127 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019128 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
19129 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
19130 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019131 }
19132 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
19133 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019134 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019135 read_Machine_DumpInfo($ABI, $LibVersion);
19136 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019137 if(not $SymbolInfo{$LibVersion})
19138 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019139 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019140 }
19141 if(not keys(%{$SymbolInfo{$LibVersion}}))
19142 { # validation of old-version dumps
19143 if(not $ExtendedCheck) {
19144 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
19145 }
19146 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019147 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019148 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019149 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019150 else
19151 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019152 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019153 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019154 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019155 }
19156 if(not $DepSymbols)
19157 { # Cannot reconstruct DepSymbols. This may result in false
19158 # positives if the old dump is for library 2. Not a problem if
19159 # old dumps are only from old libraries.
19160 $DepSymbols = {};
19161 }
19162 foreach my $Symbol (keys(%{$DepSymbols})) {
19163 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
19164 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019165 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019166 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
19167 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
19168 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019169 if(not $SkipTypes{$LibVersion})
19170 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019171 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019172 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019173 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019174 if(not $SkipSymbols{$LibVersion})
19175 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019176 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019177 }
19178 if(not $SkipSymbols{$LibVersion})
19179 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019180 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019181 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019182 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
19183 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
19184 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019185 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019186 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019187 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019188 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019189 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019190 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019191 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019192 if(not checkDump($LibVersion, "2.10.1")
19193 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019194 { # support for old ABI dumps: added target headers
19195 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
19196 $TargetHeaders{$LibVersion}{get_filename($_)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019197 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019198 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
19199 $TargetHeaders{$LibVersion}{get_filename($_)}=1;
19200 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019201 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019202 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019203 if(defined $ABI->{"GccConstants"})
19204 { # 3.0
19205 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
19206 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
19207 }
19208 }
19209
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019210 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019211 if(not $NestedNameSpaces{$LibVersion})
19212 { # support for old dumps
19213 # Cannot reconstruct NameSpaces. This may affect design
19214 # of the compatibility report.
19215 $NestedNameSpaces{$LibVersion} = {};
19216 }
19217 # target system type
19218 # needed to adopt HTML report
19219 if(not $DumpSystem)
19220 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019221 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019222 }
19223 # recreate environment
19224 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
19225 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019226 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019227 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019228 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19229 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019230 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019231 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019232 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019233 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19234 {
19235 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19236 setLanguage($LibVersion, "C++");
19237 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019238 }
19239 }
19240 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019241 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
19242 {
19243 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
19244 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19245 }
19246 }
19247
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019248 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019249 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019250 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019251 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019252 {
19253 if(not $Symbol_Library{$LibVersion}{$MnglName}
19254 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
19255 push(@VFunc, $MnglName);
19256 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019257 }
19258 }
19259 translateSymbols(@VFunc, $LibVersion);
19260 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019261 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
19262
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019263 if(not checkDump($LibVersion, "3.0"))
19264 { # support for old ABI dumps
19265 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
19266 {
19267 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
19268 {
19269 if(ref($BaseType) eq "HASH") {
19270 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
19271 }
19272 }
19273 }
19274 }
19275
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019276 if(not checkDump($LibVersion, "2.20"))
19277 { # support for old ABI dumps
19278 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
19279 {
19280 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
19281
19282 if($TType=~/Struct|Union|Enum|Typedef/)
19283 { # repair complex types first
19284 next;
19285 }
19286
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019287 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019288 {
19289 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
19290 if($BType=~/Struct|Union|Enum/i)
19291 {
19292 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
19293 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
19294 }
19295 }
19296 }
19297 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
19298 {
19299 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
19300 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
19301 if($TType=~/Struct|Union|Enum/) {
19302 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
19303 }
19304 }
19305 }
19306
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019307 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019308 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019309 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
19310 { # support for old ABI dumps < 2.0 (ACC 1.22)
19311 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
19312 {
19313 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
19314 {
19315 if($Access ne "public") {
19316 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
19317 }
19318 }
19319 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
19320 }
19321 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
19322 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019323 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
19324 { # support for old ABI dumps
19325 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
19326 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019327 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
19328 { # DWARF ABI Dumps
19329 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
19330 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019331 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
19332 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
19333 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019334 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
19335 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019336 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019337 foreach (keys(%{$TInfo{"Base"}})) {
19338 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019339 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019340 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019341 if($TInfo{"Type"} eq "MethodPtr")
19342 {
19343 if(defined $TInfo{"Param"})
19344 { # support for old ABI dumps <= 1.17
19345 if(not defined $TInfo{"Param"}{"0"})
19346 {
19347 my $Max = keys(%{$TInfo{"Param"}});
19348 foreach my $Pos (1 .. $Max) {
19349 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
19350 }
19351 delete($TInfo{"Param"}{$Max});
19352 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
19353 }
19354 }
19355 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019356 if($TInfo{"BaseType"} eq $TypeId)
19357 { # fix ABI dump
19358 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
19359 }
19360 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019361 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019362 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019363 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019364 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
19365 if(not $BName)
19366 { # broken type
19367 next;
19368 }
19369 if($TInfo{"Name"} eq $BName)
19370 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019371 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019372 next;
19373 }
19374 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
19375 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019376 }
19377 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019378 }
19379 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
19380 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019381 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019382 }
19383 }
19384
19385 if(not checkDump($LibVersion, "2.15"))
19386 { # support for old ABI dumps
19387 my %Dups = ();
19388 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
19389 {
19390 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019391 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019392 if(not defined $TypeInfo{$LibVersion}{$ClassId})
19393 { # remove template decls
19394 delete($SymbolInfo{$LibVersion}{$InfoId});
19395 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019396 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019397 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040019398 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
19399 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019400 { # templates
19401 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019402 }
19403 }
19404 }
19405
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019406 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
19407 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040019408 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
19409 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
19410 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
19411 { # support for old ABI dumps (< 3.1)
19412 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
19413 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
19414 { # add "this" first parameter
19415 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
19416 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
19417
19418 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
19419 {
19420 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
19421 foreach my $Pos (reverse(0 .. $#Pos)) {
19422 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
19423 }
19424 }
19425 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
19426 }
19427 }
19428
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019429 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
19430 { # ABI dumps have no mangled names for C-functions
19431 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
19432 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019433 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
19434 { # support for old ABI dumps
19435 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
19436 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019437 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
19438 { # DWARF ABI Dumps
19439 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
19440 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019441 }
19442
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019443 $Descriptor{$LibVersion}{"Dump"} = 1;
19444}
19445
19446sub read_Machine_DumpInfo($$)
19447{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019448 my ($ABI, $LibVersion) = @_;
19449 if($ABI->{"Arch"}) {
19450 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019451 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019452 if($ABI->{"WordSize"}) {
19453 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019454 }
19455 else
19456 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019457 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019458 }
19459 if(not $WORD_SIZE{$LibVersion})
19460 { # support for old dumps (<1.23)
19461 if(my $Tid = getTypeIdByName("char*", $LibVersion))
19462 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019463 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019464 }
19465 else
19466 {
19467 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019468 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019469 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019470 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
19471 { # any "pointer"-type
19472 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019473 last;
19474 }
19475 }
19476 if($PSize)
19477 { # a pointer type size
19478 $WORD_SIZE{$LibVersion} = $PSize;
19479 }
19480 else {
19481 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
19482 }
19483 }
19484 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019485 if($ABI->{"GccVersion"}) {
19486 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019487 }
19488}
19489
19490sub read_Libs_DumpInfo($$)
19491{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019492 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019493 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
19494 if(not $Library_Symbol{$LibVersion})
19495 { # support for old dumps
19496 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
19497 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019498 if(keys(%{$Library_Symbol{$LibVersion}})
19499 and not $DumpAPI) {
19500 $Descriptor{$LibVersion}{"Libs"} = "OK";
19501 }
19502}
19503
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019504sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019505{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019506 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019507
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019508 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019509 and not $DumpAPI) {
19510 $Descriptor{$LibVersion}{"Headers"} = "OK";
19511 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019512 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019513 { # headers info is stored in the old dumps in the different way
19514 if($UseOldDumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019515 and my $Name = $ABI->{"Headers"}{$Identity}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019516 { # support for old dumps: headers info corrected in 1.22
19517 $Identity = $Name;
19518 }
19519 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019520 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019521 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019522
19523 if(keys(%{$ABI->{"Sources"}})
19524 and not $DumpAPI) {
19525 $Descriptor{$LibVersion}{"Sources"} = "OK";
19526 }
19527 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
19528 { # headers info is stored in the old dumps in the different way
19529 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
19530 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
19531 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019532}
19533
19534sub find_libs($$$)
19535{
19536 my ($Path, $Type, $MaxDepth) = @_;
19537 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019538 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019539}
19540
19541sub createDescriptor($$)
19542{
19543 my ($LibVersion, $Path) = @_;
19544 if(not $LibVersion or not $Path
19545 or not -e $Path) {
19546 return "";
19547 }
19548 if(-d $Path)
19549 { # directory with headers files and shared objects
19550 return "
19551 <version>
19552 ".$TargetVersion{$LibVersion}."
19553 </version>
19554
19555 <headers>
19556 $Path
19557 </headers>
19558
19559 <libs>
19560 $Path
19561 </libs>";
19562 }
19563 else
19564 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019565 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019566 { # standard XML-descriptor
19567 return readFile($Path);
19568 }
19569 elsif(is_header($Path, 2, $LibVersion))
19570 { # header file
19571 return "
19572 <version>
19573 ".$TargetVersion{$LibVersion}."
19574 </version>
19575
19576 <headers>
19577 $Path
19578 </headers>
19579
19580 <libs>
19581 none
19582 </libs>";
19583 }
19584 elsif(parse_libname($Path, "name", $OStarget))
19585 { # shared object
19586 return "
19587 <version>
19588 ".$TargetVersion{$LibVersion}."
19589 </version>
19590
19591 <headers>
19592 none
19593 </headers>
19594
19595 <libs>
19596 $Path
19597 </libs>";
19598 }
19599 else
19600 { # standard XML-descriptor
19601 return readFile($Path);
19602 }
19603 }
19604}
19605
19606sub detect_lib_default_paths()
19607{
19608 my %LPaths = ();
19609 if($OSgroup eq "bsd")
19610 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019611 if(my $LdConfig = get_CmdPath("ldconfig"))
19612 {
19613 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
19614 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019615 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
19616 {
19617 my $Name = "lib".$1;
19618 if(not defined $LPaths{$Name}) {
19619 $LPaths{$Name} = $2;
19620 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019621 }
19622 }
19623 }
19624 else {
19625 printMsg("WARNING", "can't find ldconfig");
19626 }
19627 }
19628 else
19629 {
19630 if(my $LdConfig = get_CmdPath("ldconfig"))
19631 {
19632 if($SystemRoot and $OSgroup eq "linux")
19633 { # use host (x86) ldconfig with the target (arm) ld.so.conf
19634 if(-e $SystemRoot."/etc/ld.so.conf") {
19635 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
19636 }
19637 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019638 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
19639 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019640 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
19641 {
19642 my ($Name, $Path) = ($1, $2);
19643 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019644 if(not defined $LPaths{$Name})
19645 { # get first element from the list of available paths
19646
19647 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
19648 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
19649 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
19650
19651 $LPaths{$Name} = $Path;
19652 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019653 }
19654 }
19655 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040019656 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019657 printMsg("WARNING", "can't find ldconfig");
19658 }
19659 }
19660 return \%LPaths;
19661}
19662
19663sub detect_bin_default_paths()
19664{
19665 my $EnvPaths = $ENV{"PATH"};
19666 if($OSgroup eq "beos") {
19667 $EnvPaths.=":".$ENV{"BETOOLS"};
19668 }
19669 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019670 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019671 {
19672 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019673 next if(not $Path);
19674 if($SystemRoot
19675 and $Path=~/\A\Q$SystemRoot\E\//)
19676 { # do NOT use binaries from target system
19677 next;
19678 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019679 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019680 }
19681}
19682
19683sub detect_inc_default_paths()
19684{
19685 return () if(not $GCC_PATH);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019686 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019687 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019688 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019689 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019690 next if(index($Line, "/cc1plus ")!=-1);
19691
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019692 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
19693 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019694 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019695 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019696 if(index($Path, "c++")!=-1
19697 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019698 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019699 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019700 if(not defined $MAIN_CPP_DIR
19701 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
19702 $MAIN_CPP_DIR = $Path;
19703 }
19704 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019705 elsif(index($Path, "gcc")!=-1) {
19706 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019707 }
19708 else
19709 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019710 if($Path=~/local[\/\\]+include/)
19711 { # local paths
19712 next;
19713 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019714 if($SystemRoot
19715 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
19716 { # The GCC include path for user headers is not a part of the system root
19717 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
19718 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
19719 next;
19720 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019721 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019722 }
19723 }
19724 }
19725 unlink("$TMP_DIR/empty.h");
19726 return %DPaths;
19727}
19728
19729sub detect_default_paths($)
19730{
19731 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
19732 my $Search = $_[0];
19733 if($Search!~/inc/) {
19734 $HSearch = 0;
19735 }
19736 if($Search!~/lib/) {
19737 $LSearch = 0;
19738 }
19739 if($Search!~/bin/) {
19740 $BSearch = 0;
19741 }
19742 if($Search!~/gcc/) {
19743 $GSearch = 0;
19744 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019745 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019746 { # <search_headers> section of the XML descriptor
19747 # do NOT search for systems headers
19748 $HSearch = 0;
19749 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019750 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019751 { # <search_headers> section of the XML descriptor
19752 # do NOT search for systems headers
19753 $LSearch = 0;
19754 }
19755 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
19756 { # additional search paths
19757 next if($Type eq "include" and not $HSearch);
19758 next if($Type eq "lib" and not $LSearch);
19759 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019760 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019761 }
19762 if($OSgroup ne "windows")
19763 { # unix-like
19764 foreach my $Type ("include", "lib", "bin")
19765 { # automatic detection of system "devel" directories
19766 next if($Type eq "include" and not $HSearch);
19767 next if($Type eq "lib" and not $LSearch);
19768 next if($Type eq "bin" and not $BSearch);
19769 my ($UsrDir, $RootDir) = ("/usr", "/");
19770 if($SystemRoot and $Type ne "bin")
19771 { # 1. search for target headers and libraries
19772 # 2. use host commands: ldconfig, readelf, etc.
19773 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
19774 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019775 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019776 if(-d $RootDir."/".$Type)
19777 { # if "/lib" is symbolic link
19778 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019779 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019780 }
19781 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019782 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019783 }
19784 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019785 if(-d $UsrDir)
19786 {
19787 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019788 if(-d $UsrDir."/".$Type)
19789 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019790 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019791 }
19792 }
19793 }
19794 }
19795 if($BSearch)
19796 {
19797 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019798 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019799 }
19800 # check environment variables
19801 if($OSgroup eq "beos")
19802 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019803 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019804 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019805 if($_ eq ".") {
19806 next;
19807 }
19808 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
19809 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
19810 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019811 }
19812 }
19813 if($HSearch)
19814 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019815 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
19816 split(/:|;/, $ENV{"BEINCLUDES"})
19817 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019818 }
19819 if($LSearch)
19820 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019821 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
19822 split(/:|;/, $ENV{"BELIBRARIES"}),
19823 split(/:|;/, $ENV{"LIBRARY_PATH"})
19824 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019825 }
19826 }
19827 if($LSearch)
19828 { # using linker to get system paths
19829 if(my $LPaths = detect_lib_default_paths())
19830 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019831 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019832 foreach my $Name (keys(%{$LPaths}))
19833 {
19834 if($SystemRoot
19835 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
19836 { # wrong ldconfig configuration
19837 # check your <sysroot>/etc/ld.so.conf
19838 next;
19839 }
19840 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019841 if(my $Dir = get_dirname($LPaths->{$Name})) {
19842 $Dirs{$Dir} = 1;
19843 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019844 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019845 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019846 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019847 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019848 }
19849 if($BSearch)
19850 {
19851 if($CrossGcc)
19852 { # --cross-gcc=arm-linux-gcc
19853 if(-e $CrossGcc)
19854 { # absolute or relative path
19855 $GCC_PATH = get_abs_path($CrossGcc);
19856 }
19857 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
19858 { # command name
19859 $GCC_PATH = $CrossGcc;
19860 }
19861 else {
19862 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
19863 }
19864 if($GCC_PATH=~/\s/) {
19865 $GCC_PATH = "\"".$GCC_PATH."\"";
19866 }
19867 }
19868 }
19869 if($GSearch)
19870 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019871 if(not $CrossGcc)
19872 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019873 $GCC_PATH = get_CmdPath("gcc");
19874 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019875 if(not $GCC_PATH)
19876 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019877 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019878 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019879 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019880 { # select the latest version
19881 @GCCs = sort {$b cmp $a} @GCCs;
19882 if(check_gcc($GCCs[0], "3"))
19883 {
19884 $GCC_PATH = $GCCs[0];
19885 last;
19886 }
19887 }
19888 }
19889 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019890 if(not $GCC_PATH) {
19891 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
19892 }
19893 if(not $CheckObjectsOnly_Opt)
19894 {
19895 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
19896 {
19897 my $GccTarget = get_dumpmachine($GCC_PATH);
19898 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget)");
19899 if($GccTarget=~/symbian/)
19900 {
19901 $OStarget = "symbian";
19902 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
19903 }
19904 }
19905 else {
19906 exitStatus("Error", "something is going wrong with the GCC compiler");
19907 }
19908 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019909 if($HSearch)
19910 {
19911 if(not $NoStdInc)
19912 { # do NOT search in GCC standard paths
19913 my %DPaths = detect_inc_default_paths();
19914 @DefaultCppPaths = @{$DPaths{"Cpp"}};
19915 @DefaultGccPaths = @{$DPaths{"Gcc"}};
19916 @DefaultIncPaths = @{$DPaths{"Inc"}};
19917 push_U($SystemPaths{"include"}, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019918 }
19919 }
19920 }
19921 if($HSearch)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019922 { # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040019923 my $IncPath = "/usr/include";
19924 if($SystemRoot) {
19925 $IncPath = $SystemRoot.$IncPath;
19926 }
19927 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019928 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019929 }
19930 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019931
19932 if($ExtraInfo)
19933 {
19934 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
19935 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
19936 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019937}
19938
19939sub getLIB_EXT($)
19940{
19941 my $Target = $_[0];
19942 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
19943 return $Ext;
19944 }
19945 return $OS_LibExt{$LIB_TYPE}{"default"};
19946}
19947
19948sub getAR_EXT($)
19949{
19950 my $Target = $_[0];
19951 if(my $Ext = $OS_Archive{$Target}) {
19952 return $Ext;
19953 }
19954 return $OS_Archive{"default"};
19955}
19956
19957sub get_dumpversion($)
19958{
19959 my $Cmd = $_[0];
19960 return "" if(not $Cmd);
19961 if($Cache{"get_dumpversion"}{$Cmd}) {
19962 return $Cache{"get_dumpversion"}{$Cmd};
19963 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019964 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019965 chomp($V);
19966 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
19967}
19968
19969sub get_dumpmachine($)
19970{
19971 my $Cmd = $_[0];
19972 return "" if(not $Cmd);
19973 if($Cache{"get_dumpmachine"}{$Cmd}) {
19974 return $Cache{"get_dumpmachine"}{$Cmd};
19975 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019976 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019977 chomp($Machine);
19978 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
19979}
19980
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019981sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019982{
19983 my $Cmd = $_[0];
19984 return "" if(not $Cmd);
19985 my @Options = (
19986 "--version",
19987 "-help"
19988 );
19989 foreach my $Opt (@Options)
19990 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019991 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019992 if($Info) {
19993 return 1;
19994 }
19995 }
19996 return 0;
19997}
19998
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019999sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020000{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020001 my ($Cmd, $ReqVer) = @_;
20002 return 0 if(not $Cmd or not $ReqVer);
20003 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
20004 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020005 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020006 if(my $GccVer = get_dumpversion($Cmd))
20007 {
20008 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
20009 if(cmpVersions($GccVer, $ReqVer)>=0) {
20010 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
20011 }
20012 }
20013 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020014}
20015
20016sub get_depth($)
20017{
20018 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020019 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020020 }
20021 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
20022}
20023
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020024sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020025{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020026 return if($Cache{"registerGccHeaders"}); # this function should be called once
20027
20028 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020029 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020030 my @Headers = cmd_find($Path,"f");
20031 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20032 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020033 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020034 my $FileName = get_filename($HPath);
20035 if(not defined $DefaultGccHeader{$FileName})
20036 { # skip duplicated
20037 $DefaultGccHeader{$FileName} = $HPath;
20038 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020039 }
20040 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020041 $Cache{"registerGccHeaders"} = 1;
20042}
20043
20044sub registerCppHeaders()
20045{
20046 return if($Cache{"registerCppHeaders"}); # this function should be called once
20047
20048 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020049 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020050 my @Headers = cmd_find($CppDir,"f");
20051 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20052 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020053 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020054 my $FileName = get_filename($Path);
20055 if(not defined $DefaultCppHeader{$FileName})
20056 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020057 $DefaultCppHeader{$FileName} = $Path;
20058 }
20059 }
20060 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020061 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020062}
20063
20064sub parse_libname($$$)
20065{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020066 return "" if(not $_[0]);
20067 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
20068 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020069 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020070 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
20071}
20072
20073sub parse_libname_I($$$)
20074{
20075 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020076
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020077 if($Target eq "symbian") {
20078 return parse_libname_symbian($Name, $Type);
20079 }
20080 elsif($Target eq "windows") {
20081 return parse_libname_windows($Name, $Type);
20082 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020083
20084 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020085 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020086 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020087 { # libSDL-1.2.so.0.7.1
20088 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020089 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020090 if($Type eq "name")
20091 { # libSDL-1.2
20092 # libwbxml2
20093 return $2;
20094 }
20095 elsif($Type eq "name+ext")
20096 { # libSDL-1.2.so
20097 # libwbxml2.so
20098 return $1;
20099 }
20100 elsif($Type eq "version")
20101 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020102 if(defined $7
20103 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020104 { # 0.7.1
20105 return $7;
20106 }
20107 else
20108 { # libc-2.5.so (=>2.5 version)
20109 my $MV = $5;
20110 $MV=~s/\A[\-\_]+//g;
20111 return $MV;
20112 }
20113 }
20114 elsif($Type eq "short")
20115 { # libSDL
20116 # libwbxml2
20117 return $3;
20118 }
20119 elsif($Type eq "shortest")
20120 { # SDL
20121 # wbxml
20122 return shortest_name($3);
20123 }
20124 }
20125 return "";# error
20126}
20127
20128sub parse_libname_symbian($$)
20129{
20130 my ($Name, $Type) = @_;
20131 my $Ext = getLIB_EXT("symbian");
20132 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
20133 { # libpthread{00010001}.dso
20134 if($Type eq "name")
20135 { # libpthread{00010001}
20136 return $2;
20137 }
20138 elsif($Type eq "name+ext")
20139 { # libpthread{00010001}.dso
20140 return $1;
20141 }
20142 elsif($Type eq "version")
20143 { # 00010001
20144 my $V = $4;
20145 $V=~s/\{(.+)\}/$1/;
20146 return $V;
20147 }
20148 elsif($Type eq "short")
20149 { # libpthread
20150 return $3;
20151 }
20152 elsif($Type eq "shortest")
20153 { # pthread
20154 return shortest_name($3);
20155 }
20156 }
20157 return "";# error
20158}
20159
20160sub parse_libname_windows($$)
20161{
20162 my ($Name, $Type) = @_;
20163 my $Ext = getLIB_EXT("windows");
20164 if($Name=~/((.+?)\.$Ext)\Z/)
20165 { # netapi32.dll
20166 if($Type eq "name")
20167 { # netapi32
20168 return $2;
20169 }
20170 elsif($Type eq "name+ext")
20171 { # netapi32.dll
20172 return $1;
20173 }
20174 elsif($Type eq "version")
20175 { # DLL version embedded
20176 # at binary-level
20177 return "";
20178 }
20179 elsif($Type eq "short")
20180 { # netapi32
20181 return $2;
20182 }
20183 elsif($Type eq "shortest")
20184 { # netapi
20185 return shortest_name($2);
20186 }
20187 }
20188 return "";# error
20189}
20190
20191sub shortest_name($)
20192{
20193 my $Name = $_[0];
20194 # remove prefix
20195 $Name=~s/\A(lib|open)//;
20196 # remove suffix
20197 $Name=~s/[\W\d_]+\Z//i;
20198 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
20199 return $Name;
20200}
20201
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020202sub createSymbolsList($$$$$)
20203{
20204 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
20205 read_ABI_Dump(1, $DPath);
20206 if(not $CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020207 prepareSymbols(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020208 }
20209 my %SymbolHeaderLib = ();
20210 my $Total = 0;
20211 # Get List
20212 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
20213 {
20214 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020215 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020216 next;
20217 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020218 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020219 { # skip other symbols
20220 next;
20221 }
20222 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
20223 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020224 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020225 next;
20226 }
20227 my $DyLib = $Symbol_Library{1}{$Symbol};
20228 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020229 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020230 next;
20231 }
20232 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
20233 $Total+=1;
20234 }
20235 # Draw List
20236 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
20237 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
20238 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
20239 {
20240 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
20241 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020242 my %NS_Symbol = ();
20243 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020244 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020245 }
20246 foreach my $NameSpace (sort keys(%NS_Symbol))
20247 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020248 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020249 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
20250 foreach my $Symbol (@SortedInterfaces)
20251 {
20252 my $SubReport = "";
20253 my $Signature = get_Signature($Symbol, 1);
20254 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020255 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020256 }
20257 if($Symbol=~/\A(_Z|\?)/)
20258 {
20259 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020260 $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 +040020261 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020262 else {
20263 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
20264 }
20265 }
20266 else
20267 {
20268 if($Signature) {
20269 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
20270 }
20271 else {
20272 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
20273 }
20274 }
20275 $SYMBOLS_LIST .= $SubReport;
20276 }
20277 }
20278 $SYMBOLS_LIST .= "<br/>\n";
20279 }
20280 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020281 # clear info
20282 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
20283 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
20284 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
20285 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020286 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020287 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020288 my $CssStyles = readModule("Styles", "SymbolsList.css");
20289 my $JScripts = readModule("Scripts", "Sections.js");
20290 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020291 my $Title = "$LName: public symbols";
20292 my $Keywords = "$LName, API, symbols";
20293 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020294 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020295 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020296 <br/><br/><hr/>\n".getReportFooter($LName, 1)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020297 <div style='height:999px;'></div></body></html>";
20298 writeFile($SaveTo, $SYMBOLS_LIST);
20299}
20300
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020301sub add_target_libs($)
20302{
20303 foreach (@{$_[0]}) {
20304 $TargetLibs{$_} = 1;
20305 }
20306}
20307
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020308sub is_target_lib($)
20309{
20310 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020311 if(not $LName) {
20312 return 0;
20313 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020314 if($TargetLibraryName
20315 and $LName!~/\Q$TargetLibraryName\E/) {
20316 return 0;
20317 }
20318 if(keys(%TargetLibs)
20319 and not $TargetLibs{$LName}
20320 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
20321 return 0;
20322 }
20323 return 1;
20324}
20325
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020326sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020327{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020328 my ($H, $V) = @_;
20329 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020330 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020331 if($TargetHeaders{$V}{$H}) {
20332 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020333 }
20334 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020335 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020336}
20337
20338sub checkVersionNum($$)
20339{
20340 my ($LibVersion, $Path) = @_;
20341 if(my $VerNum = $TargetVersion{$LibVersion}) {
20342 return $VerNum;
20343 }
20344 my $UsedAltDescr = 0;
20345 foreach my $Part (split(/\s*,\s*/, $Path))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020346 { # try to get version string from file path
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020347 next if(isDump($Part)); # ABI dump
20348 next if($Part=~/\.(xml|desc)\Z/i); # XML descriptor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020349 my $VerNum = "";
20350 if(parse_libname($Part, "name", $OStarget))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020351 {
20352 $UsedAltDescr = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020353 $VerNum = parse_libname($Part, "version", $OStarget);
20354 if(not $VerNum) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040020355 $VerNum = readStrVer($Part);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020356 }
20357 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020358 elsif(is_header($Part, 2, $LibVersion) or -d $Part)
20359 {
20360 $UsedAltDescr = 1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040020361 $VerNum = readStrVer($Part);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020362 }
20363 if($VerNum ne "")
20364 {
20365 $TargetVersion{$LibVersion} = $VerNum;
20366 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020367 printMsg("WARNING", "setting version number to $VerNum (use -vnum option to change it)");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020368 }
20369 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020370 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 +040020371 }
20372 return $TargetVersion{$LibVersion};
20373 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020374 }
20375 if($UsedAltDescr)
20376 {
20377 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020378 exitStatus("Error", "version number is not set (use -vnum option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020379 }
20380 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020381 exitStatus("Error", ($LibVersion==1?"1st":"2nd")." version number is not set (use -v$LibVersion option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020382 }
20383 }
20384}
20385
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040020386sub readStrVer($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020387{
20388 my $Str = $_[0];
20389 return "" if(not $Str);
20390 $Str=~s/\Q$TargetLibraryName\E//g;
20391 if($Str=~/(\/|\\|\w|\A)[\-\_]*(\d+[\d\.\-]+\d+|\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020392 { # .../libssh-0.4.0/...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020393 return $2;
20394 }
20395 elsif(my $V = parse_libname($Str, "version", $OStarget)) {
20396 return $V;
20397 }
20398 return "";
20399}
20400
20401sub readLibs($)
20402{
20403 my $LibVersion = $_[0];
20404 if($OStarget eq "windows")
20405 { # dumpbin.exe will crash
20406 # without VS Environment
20407 check_win32_env();
20408 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020409 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020410 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020411 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020412}
20413
20414sub dump_sorting($)
20415{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040020416 my $Hash = $_[0];
20417 return [] if(not $Hash);
20418 my @Keys = keys(%{$Hash});
20419 return [] if($#Keys<0);
20420 if($Keys[0]=~/\A\d+\Z/)
20421 { # numbers
20422 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020423 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040020424 else
20425 { # strings
20426 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020427 }
20428}
20429
20430sub printMsg($$)
20431{
20432 my ($Type, $Msg) = @_;
20433 if($Type!~/\AINFO/) {
20434 $Msg = $Type.": ".$Msg;
20435 }
20436 if($Type!~/_C\Z/) {
20437 $Msg .= "\n";
20438 }
20439 if($Quiet)
20440 { # --quiet option
20441 appendFile($COMMON_LOG_PATH, $Msg);
20442 }
20443 else
20444 {
20445 if($Type eq "ERROR") {
20446 print STDERR $Msg;
20447 }
20448 else {
20449 print $Msg;
20450 }
20451 }
20452}
20453
20454sub exitStatus($$)
20455{
20456 my ($Code, $Msg) = @_;
20457 printMsg("ERROR", $Msg);
20458 exit($ERROR_CODE{$Code});
20459}
20460
20461sub exitReport()
20462{ # the tool has run without any errors
20463 printReport();
20464 if($COMPILE_ERRORS)
20465 { # errors in headers may add false positives/negatives
20466 exit($ERROR_CODE{"Compile_Error"});
20467 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020468 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
20469 { # --binary
20470 exit($ERROR_CODE{"Incompatible"});
20471 }
20472 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
20473 { # --source
20474 exit($ERROR_CODE{"Incompatible"});
20475 }
20476 elsif($RESULT{"Source"}{"Problems"}
20477 or $RESULT{"Binary"}{"Problems"})
20478 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020479 exit($ERROR_CODE{"Incompatible"});
20480 }
20481 else {
20482 exit($ERROR_CODE{"Compatible"});
20483 }
20484}
20485
20486sub readRules($)
20487{
20488 my $Kind = $_[0];
20489 if(not -f $RULES_PATH{$Kind}) {
20490 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
20491 }
20492 my $Content = readFile($RULES_PATH{$Kind});
20493 while(my $Rule = parseTag(\$Content, "rule"))
20494 {
20495 my $RId = parseTag(\$Rule, "id");
20496 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
20497 foreach my $Prop (@Properties) {
20498 if(my $Value = parseTag(\$Rule, lc($Prop)))
20499 {
20500 $Value=~s/\n[ ]*//;
20501 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
20502 }
20503 }
20504 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
20505 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
20506 }
20507 else {
20508 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
20509 }
20510 }
20511}
20512
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020513sub getReportPath($)
20514{
20515 my $Level = $_[0];
20516 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
20517 if($Level eq "Binary")
20518 {
20519 if($BinaryReportPath)
20520 { # --bin-report-path
20521 return $BinaryReportPath;
20522 }
20523 elsif($OutputReportPath)
20524 { # --report-path
20525 return $OutputReportPath;
20526 }
20527 else
20528 { # default
20529 return $Dir."/abi_compat_report.$ReportFormat";
20530 }
20531 }
20532 elsif($Level eq "Source")
20533 {
20534 if($SourceReportPath)
20535 { # --src-report-path
20536 return $SourceReportPath;
20537 }
20538 elsif($OutputReportPath)
20539 { # --report-path
20540 return $OutputReportPath;
20541 }
20542 else
20543 { # default
20544 return $Dir."/src_compat_report.$ReportFormat";
20545 }
20546 }
20547 else
20548 {
20549 if($OutputReportPath)
20550 { # --report-path
20551 return $OutputReportPath;
20552 }
20553 else
20554 { # default
20555 return $Dir."/compat_report.$ReportFormat";
20556 }
20557 }
20558}
20559
20560sub printStatMsg($)
20561{
20562 my $Level = $_[0];
20563 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
20564}
20565
20566sub listAffected($)
20567{
20568 my $Level = $_[0];
20569 my $List = "";
20570 foreach (keys(%{$TotalAffected{$Level}}))
20571 {
20572 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
20573 { # skip "Low"-severity problems
20574 next;
20575 }
20576 $List .= "$_\n";
20577 }
20578 my $Dir = get_dirname(getReportPath($Level));
20579 if($Level eq "Binary") {
20580 writeFile($Dir."/abi_affected.txt", $List);
20581 }
20582 elsif($Level eq "Source") {
20583 writeFile($Dir."/src_affected.txt", $List);
20584 }
20585}
20586
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020587sub printReport()
20588{
20589 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020590 createReport();
20591 if($JoinReport or $DoubleReport)
20592 {
20593 if($RESULT{"Binary"}{"Problems"}
20594 or $RESULT{"Source"}{"Problems"}) {
20595 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020596 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020597 else {
20598 printMsg("INFO", "result: COMPATIBLE");
20599 }
20600 printStatMsg("Binary");
20601 printStatMsg("Source");
20602 if($ListAffected)
20603 { # --list-affected
20604 listAffected("Binary");
20605 listAffected("Source");
20606 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020607 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020608 elsif($BinaryOnly)
20609 {
20610 if($RESULT{"Binary"}{"Problems"}) {
20611 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
20612 }
20613 else {
20614 printMsg("INFO", "result: COMPATIBLE");
20615 }
20616 printStatMsg("Binary");
20617 if($ListAffected)
20618 { # --list-affected
20619 listAffected("Binary");
20620 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020621 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020622 elsif($SourceOnly)
20623 {
20624 if($RESULT{"Source"}{"Problems"}) {
20625 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
20626 }
20627 else {
20628 printMsg("INFO", "result: COMPATIBLE");
20629 }
20630 printStatMsg("Source");
20631 if($ListAffected)
20632 { # --list-affected
20633 listAffected("Source");
20634 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020635 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020636 if($StdOut)
20637 {
20638 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040020639 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020640 printMsg("INFO", "compatibility report has been generated to stdout");
20641 }
20642 else
20643 { # default
20644 printMsg("INFO", "compatibility reports have been generated to stdout");
20645 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020646 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020647 else
20648 {
20649 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040020650 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020651 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
20652 }
20653 elsif($DoubleReport)
20654 { # default
20655 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
20656 }
20657 elsif($BinaryOnly)
20658 { # --binary
20659 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
20660 }
20661 elsif($SourceOnly)
20662 { # --source
20663 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
20664 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020665 }
20666}
20667
20668sub check_win32_env()
20669{
20670 if(not $ENV{"DevEnvDir"}
20671 or not $ENV{"LIB"}) {
20672 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
20673 }
20674}
20675
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020676sub diffSets($$)
20677{
20678 my ($S1, $S2) = @_;
20679 my @SK1 = keys(%{$S1});
20680 my @SK2 = keys(%{$S2});
20681 if($#SK1!=$#SK2) {
20682 return 1;
20683 }
20684 foreach my $K1 (@SK1)
20685 {
20686 if(not defined $S2->{$K1}) {
20687 return 1;
20688 }
20689 }
20690 return 0;
20691}
20692
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020693sub create_ABI_Dump()
20694{
20695 if(not -e $DumpAPI) {
20696 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
20697 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020698 my @DParts = split(/\s*,\s*/, $DumpAPI);
20699 foreach my $Part (@DParts)
20700 {
20701 if(not -e $Part) {
20702 exitStatus("Access_Error", "can't access \'$Part\'");
20703 }
20704 }
20705 checkVersionNum(1, $DumpAPI);
20706 foreach my $Part (@DParts)
20707 {
20708 if(isDump($Part)) {
20709 read_ABI_Dump(1, $Part);
20710 }
20711 else {
20712 readDescriptor(1, createDescriptor(1, $Part));
20713 }
20714 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020715
20716 if(not $Descriptor{1}{"Version"})
20717 { # set to default: X
20718 $Descriptor{1}{"Version"} = "X";
20719 }
20720
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020721 initLogging(1);
20722 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020723
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020724 my $DumpPath = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi";
20725 $DumpPath .= ".".$AR_EXT; # gzipped by default
20726 if($OutputDumpPath)
20727 { # user defined path
20728 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020729 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020730 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
20731
20732 if(not $Archive and not $StdOut)
20733 { # check archive utilities
20734 if($OSgroup eq "windows")
20735 { # using zip
20736 my $ZipCmd = get_CmdPath("zip");
20737 if(not $ZipCmd) {
20738 exitStatus("Not_Found", "can't find \"zip\"");
20739 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020740 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020741 else
20742 { # using tar and gzip
20743 my $TarCmd = get_CmdPath("tar");
20744 if(not $TarCmd) {
20745 exitStatus("Not_Found", "can't find \"tar\"");
20746 }
20747 my $GzipCmd = get_CmdPath("gzip");
20748 if(not $GzipCmd) {
20749 exitStatus("Not_Found", "can't find \"gzip\"");
20750 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020751 }
20752 }
20753
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020754 if(not $Descriptor{1}{"Dump"})
20755 {
20756 if(not $CheckHeadersOnly) {
20757 readLibs(1);
20758 }
20759 if($CheckHeadersOnly) {
20760 setLanguage(1, "C++");
20761 }
20762 if(not $CheckObjectsOnly) {
20763 searchForHeaders(1);
20764 }
20765 $WORD_SIZE{1} = detectWordSize();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020766 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020767 if(not $Descriptor{1}{"Dump"})
20768 {
20769 if($Descriptor{1}{"Headers"}) {
20770 readHeaders(1);
20771 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020772 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020773 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020774 if(not keys(%{$SymbolInfo{1}}))
20775 { # check if created dump is valid
20776 if(not $ExtendedCheck and not $CheckObjectsOnly)
20777 {
20778 if($CheckHeadersOnly) {
20779 exitStatus("Empty_Set", "the set of public symbols is empty");
20780 }
20781 else {
20782 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
20783 }
20784 }
20785 }
20786 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020787 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020788 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
20789 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020790 if($ExtraDump)
20791 { # add unmangled names to the ABI dump
20792 my @Names = ();
20793 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
20794 {
20795 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
20796 push(@Names, $MnglName);
20797 }
20798 }
20799 translateSymbols(@Names, 1);
20800 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
20801 {
20802 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
20803 {
20804 if(my $Unmangled = $tr_name{$MnglName})
20805 {
20806 if($MnglName ne $Unmangled) {
20807 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
20808 }
20809 }
20810 }
20811 }
20812 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020813
20814 my %GccConstants = (); # built-in GCC constants
20815 foreach my $Name (keys(%{$Constants{1}}))
20816 {
20817 if(not defined $Constants{1}{$Name}{"Header"})
20818 {
20819 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
20820 delete($Constants{1}{$Name});
20821 }
20822 }
20823
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020824 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020825 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020826 "TypeInfo" => $TypeInfo{1},
20827 "SymbolInfo" => $SymbolInfo{1},
20828 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020829 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020830 "SymbolVersion" => $SymVer{1},
20831 "LibraryVersion" => $Descriptor{1}{"Version"},
20832 "LibraryName" => $TargetLibraryName,
20833 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020834 "SkipTypes" => $SkipTypes{1},
20835 "SkipSymbols" => $SkipSymbols{1},
20836 "SkipNameSpaces" => $SkipNameSpaces{1},
20837 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020838 "Headers" => \%HeadersInfo,
20839 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020840 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020841 "NameSpaces" => $NestedNameSpaces{1},
20842 "Target" => $OStarget,
20843 "Arch" => getArch(1),
20844 "WordSize" => $WORD_SIZE{1},
20845 "GccVersion" => get_dumpversion($GCC_PATH),
20846 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
20847 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
20848 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020849 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020850 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020851 }
20852 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020853 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020854 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020855 if($ExtendedCheck)
20856 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020857 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020858 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020859 if($BinaryOnly)
20860 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020861 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020862 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020863 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020864 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020865 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020866 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
20867 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020868 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020869
20870 my $ABI_DUMP = "";
20871 if($UseXML)
20872 {
20873 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020874 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020875 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020876 else
20877 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020878 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020879 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020880 if($StdOut)
20881 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020882 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020883 printMsg("INFO", "ABI dump has been generated to stdout");
20884 return;
20885 }
20886 else
20887 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020888 my ($DDir, $DName) = separate_path($DumpPath);
20889 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020890 if(not $Archive) {
20891 $DPath = $DumpPath;
20892 }
20893
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020894 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020895
20896 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020897 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020898 close(DUMP);
20899
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020900 if(not -s $DPath) {
20901 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
20902 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040020903 if($Archive) {
20904 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040020905 }
20906
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020907 if($OutputDumpPath) {
20908 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040020909 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020910 else {
20911 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
20912 }
20913 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 +040020914 }
20915}
20916
20917sub quickEmptyReports()
20918{ # Quick "empty" reports
20919 # 4 times faster than merging equal dumps
20920 # NOTE: the dump contains the "LibraryVersion" attribute
20921 # if you change the version, then your dump will be different
20922 # OVERCOME: use -v1 and v2 options for comparing dumps
20923 # and don't change version in the XML descriptor (and dumps)
20924 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
20925 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
20926 {
20927 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
20928 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
20929 if($FilePath1 and $FilePath2)
20930 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020931 my $Line = readLineNum($FilePath1, 0);
20932 if($Line=~/xml/)
20933 { # XML format
20934 # is not supported yet
20935 return;
20936 }
20937
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020938 local $/ = undef;
20939
20940 open(DUMP1, $FilePath1);
20941 my $Content1 = <DUMP1>;
20942 close(DUMP1);
20943
20944 open(DUMP2, $FilePath2);
20945 my $Content2 = <DUMP2>;
20946 close(DUMP2);
20947
20948 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020949 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020950 # clean memory
20951 undef $Content2;
20952
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020953 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040020954 my $ABIdump = eval($Content1);
20955
20956 # clean memory
20957 undef $Content1;
20958
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020959 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020960 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 +040020961 }
20962 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020963 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020964 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
20965 }
20966 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020967 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020968 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
20969 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020970 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020971 read_Libs_DumpInfo($ABIdump, 1);
20972 read_Machine_DumpInfo($ABIdump, 1);
20973 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020974
20975 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
20976 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
20977
20978 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
20979 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
20980
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020981 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
20982 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
20983 exitReport();
20984 }
20985 }
20986 }
20987}
20988
20989sub initLogging($)
20990{
20991 my $LibVersion = $_[0];
20992 # create log directory
20993 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
20994 if($OutputLogPath{$LibVersion})
20995 { # user-defined by -log-path option
20996 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
20997 }
20998 if($LogMode ne "n") {
20999 mkpath($LOG_DIR);
21000 }
21001 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021002 if($Debug)
21003 { # debug directory
21004 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021005
21006 if(not $ExtraInfo)
21007 { # enable --extra-info
21008 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
21009 }
21010
21011 # enable --extra-dump
21012 $ExtraDump = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021013 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021014 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021015}
21016
21017sub writeLog($$)
21018{
21019 my ($LibVersion, $Msg) = @_;
21020 if($LogMode ne "n") {
21021 appendFile($LOG_PATH{$LibVersion}, $Msg);
21022 }
21023}
21024
21025sub resetLogging($)
21026{
21027 my $LibVersion = $_[0];
21028 if($LogMode!~/a|n/)
21029 { # remove old log
21030 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021031 if($Debug) {
21032 rmtree($DEBUG_PATH{$LibVersion});
21033 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021034 }
21035}
21036
21037sub printErrorLog($)
21038{
21039 my $LibVersion = $_[0];
21040 if($LogMode ne "n") {
21041 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
21042 }
21043}
21044
21045sub isDump($)
21046{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021047 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz|\.zip|\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021048 return $1;
21049 }
21050 return 0;
21051}
21052
21053sub isDump_U($)
21054{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021055 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021056 return $1;
21057 }
21058 return 0;
21059}
21060
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021061sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021062{
21063 # read input XML descriptors or ABI dumps
21064 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021065 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021066 }
21067 my @DParts1 = split(/\s*,\s*/, $Descriptor{1}{"Path"});
21068 foreach my $Part (@DParts1)
21069 {
21070 if(not -e $Part) {
21071 exitStatus("Access_Error", "can't access \'$Part\'");
21072 }
21073 }
21074 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021075 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021076 }
21077 my @DParts2 = split(/\s*,\s*/, $Descriptor{2}{"Path"});
21078 foreach my $Part (@DParts2)
21079 {
21080 if(not -e $Part) {
21081 exitStatus("Access_Error", "can't access \'$Part\'");
21082 }
21083 }
21084 detect_default_paths("bin"); # to extract dumps
21085 if($#DParts1==0 and $#DParts2==0
21086 and isDump($Descriptor{1}{"Path"})
21087 and isDump($Descriptor{2}{"Path"}))
21088 { # optimization: equal ABI dumps
21089 quickEmptyReports();
21090 }
21091 checkVersionNum(1, $Descriptor{1}{"Path"});
21092 checkVersionNum(2, $Descriptor{2}{"Path"});
21093 printMsg("INFO", "preparation, please wait ...");
21094 foreach my $Part (@DParts1)
21095 {
21096 if(isDump($Part)) {
21097 read_ABI_Dump(1, $Part);
21098 }
21099 else {
21100 readDescriptor(1, createDescriptor(1, $Part));
21101 }
21102 }
21103 foreach my $Part (@DParts2)
21104 {
21105 if(isDump($Part)) {
21106 read_ABI_Dump(2, $Part);
21107 }
21108 else {
21109 readDescriptor(2, createDescriptor(2, $Part));
21110 }
21111 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021112
21113 if(not $Descriptor{1}{"Version"})
21114 { # set to default: X
21115 $Descriptor{1}{"Version"} = "X";
21116 }
21117
21118 if(not $Descriptor{2}{"Version"})
21119 { # set to default: Y
21120 $Descriptor{2}{"Version"} = "Y";
21121 }
21122
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021123 initLogging(1);
21124 initLogging(2);
21125 # check consistency
21126 if(not $Descriptor{1}{"Headers"}
21127 and not $Descriptor{1}{"Libs"}) {
21128 exitStatus("Error", "descriptor d1 does not contain both header files and libraries info");
21129 }
21130 if(not $Descriptor{2}{"Headers"}
21131 and not $Descriptor{2}{"Libs"}) {
21132 exitStatus("Error", "descriptor d2 does not contain both header files and libraries info");
21133 }
21134 if($Descriptor{1}{"Headers"} and not $Descriptor{1}{"Libs"}
21135 and not $Descriptor{2}{"Headers"} and $Descriptor{2}{"Libs"}) {
21136 exitStatus("Error", "can't compare headers with $SLIB_TYPE libraries");
21137 }
21138 elsif(not $Descriptor{1}{"Headers"} and $Descriptor{1}{"Libs"}
21139 and $Descriptor{2}{"Headers"} and not $Descriptor{2}{"Libs"}) {
21140 exitStatus("Error", "can't compare $SLIB_TYPE libraries with headers");
21141 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021142 if(not $Descriptor{1}{"Headers"})
21143 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021144 if($CheckHeadersOnly_Opt) {
21145 exitStatus("Error", "can't find header files info in descriptor d1");
21146 }
21147 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021148 if(not $Descriptor{2}{"Headers"})
21149 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021150 if($CheckHeadersOnly_Opt) {
21151 exitStatus("Error", "can't find header files info in descriptor d2");
21152 }
21153 }
21154 if(not $Descriptor{1}{"Headers"}
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021155 or not $Descriptor{2}{"Headers"})
21156 {
21157 if(not $CheckObjectsOnly_Opt)
21158 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021159 printMsg("WARNING", "comparing $SLIB_TYPE libraries only");
21160 $CheckObjectsOnly = 1;
21161 }
21162 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021163 if(not $Descriptor{1}{"Libs"})
21164 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021165 if($CheckObjectsOnly_Opt) {
21166 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d1");
21167 }
21168 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021169 if(not $Descriptor{2}{"Libs"})
21170 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021171 if($CheckObjectsOnly_Opt) {
21172 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d2");
21173 }
21174 }
21175 if(not $Descriptor{1}{"Libs"}
21176 or not $Descriptor{2}{"Libs"})
21177 { # comparing standalone header files
21178 # comparing ABI dumps created with --headers-only
21179 if(not $CheckHeadersOnly_Opt)
21180 {
21181 printMsg("WARNING", "checking headers only");
21182 $CheckHeadersOnly = 1;
21183 }
21184 }
21185 if($UseDumps)
21186 { # --use-dumps
21187 # parallel processing
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021188 my $DumpPath1 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi.$AR_EXT";
21189 my $DumpPath2 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{2}{"Version"}.".abi.$AR_EXT";
21190
21191 unlink($DumpPath1);
21192 unlink($DumpPath2);
21193
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021194 my $pid = fork();
21195 if($pid)
21196 { # dump on two CPU cores
21197 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
21198 if($RelativeDirectory{1}) {
21199 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
21200 }
21201 if($OutputLogPath{1}) {
21202 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
21203 }
21204 if($CrossGcc) {
21205 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
21206 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021207 if($Quiet)
21208 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021209 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021210 @PARAMS = (@PARAMS, "-logging-mode", "a");
21211 }
21212 elsif($LogMode and $LogMode ne "w")
21213 { # "w" is default
21214 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021215 }
21216 if($ExtendedCheck) {
21217 @PARAMS = (@PARAMS, "-extended");
21218 }
21219 if($UserLang) {
21220 @PARAMS = (@PARAMS, "-lang", $UserLang);
21221 }
21222 if($TargetVersion{1}) {
21223 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
21224 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021225 if($BinaryOnly) {
21226 @PARAMS = (@PARAMS, "-binary");
21227 }
21228 if($SourceOnly) {
21229 @PARAMS = (@PARAMS, "-source");
21230 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021231 if($SortDump) {
21232 @PARAMS = (@PARAMS, "-sort");
21233 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021234 if($DumpFormat and $DumpFormat ne "perl") {
21235 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
21236 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021237 if($CheckHeadersOnly) {
21238 @PARAMS = (@PARAMS, "-headers-only");
21239 }
21240 if($CheckObjectsOnly) {
21241 @PARAMS = (@PARAMS, "-objects-only");
21242 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021243 if($Debug)
21244 {
21245 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021246 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021247 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021248 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021249 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021250 exit(1);
21251 }
21252 }
21253 else
21254 { # child
21255 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
21256 if($RelativeDirectory{2}) {
21257 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
21258 }
21259 if($OutputLogPath{2}) {
21260 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
21261 }
21262 if($CrossGcc) {
21263 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
21264 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021265 if($Quiet)
21266 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021267 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021268 @PARAMS = (@PARAMS, "-logging-mode", "a");
21269 }
21270 elsif($LogMode and $LogMode ne "w")
21271 { # "w" is default
21272 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021273 }
21274 if($ExtendedCheck) {
21275 @PARAMS = (@PARAMS, "-extended");
21276 }
21277 if($UserLang) {
21278 @PARAMS = (@PARAMS, "-lang", $UserLang);
21279 }
21280 if($TargetVersion{2}) {
21281 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
21282 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021283 if($BinaryOnly) {
21284 @PARAMS = (@PARAMS, "-binary");
21285 }
21286 if($SourceOnly) {
21287 @PARAMS = (@PARAMS, "-source");
21288 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021289 if($SortDump) {
21290 @PARAMS = (@PARAMS, "-sort");
21291 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021292 if($DumpFormat and $DumpFormat ne "perl") {
21293 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
21294 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021295 if($CheckHeadersOnly) {
21296 @PARAMS = (@PARAMS, "-headers-only");
21297 }
21298 if($CheckObjectsOnly) {
21299 @PARAMS = (@PARAMS, "-objects-only");
21300 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021301 if($Debug)
21302 {
21303 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021304 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021305 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021306 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021307 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021308 exit(1);
21309 }
21310 else {
21311 exit(0);
21312 }
21313 }
21314 waitpid($pid, 0);
21315 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021316 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
21317 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021318 if($TargetLibraryFName ne $TargetLibraryName) {
21319 @CMP_PARAMS = (@CMP_PARAMS, "-l-full", $TargetLibraryFName);
21320 }
21321 if($ShowRetVal) {
21322 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
21323 }
21324 if($CrossGcc) {
21325 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
21326 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021327 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
21328 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021329 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021330 }
21331 if($ReportFormat and $ReportFormat ne "html")
21332 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021333 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
21334 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021335 if($OutputReportPath) {
21336 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
21337 }
21338 if($BinaryReportPath) {
21339 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
21340 }
21341 if($SourceReportPath) {
21342 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
21343 }
21344 if($LoggingPath) {
21345 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
21346 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021347 if($CheckHeadersOnly) {
21348 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
21349 }
21350 if($CheckObjectsOnly) {
21351 @CMP_PARAMS = (@CMP_PARAMS, "-objects-only");
21352 }
21353 if($BinaryOnly) {
21354 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
21355 }
21356 if($SourceOnly) {
21357 @CMP_PARAMS = (@CMP_PARAMS, "-source");
21358 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021359 if($Browse) {
21360 @CMP_PARAMS = (@CMP_PARAMS, "-browse", $Browse);
21361 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021362 if($OpenReport) {
21363 @CMP_PARAMS = (@CMP_PARAMS, "-open");
21364 }
21365 if($Debug)
21366 {
21367 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
21368 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021369 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021370 system("perl", $0, @CMP_PARAMS);
21371 exit($?>>8);
21372 }
21373 if(not $Descriptor{1}{"Dump"}
21374 or not $Descriptor{2}{"Dump"})
21375 { # need GCC toolchain to analyze
21376 # header files and libraries
21377 detect_default_paths("inc|lib|gcc");
21378 }
21379 if(not $Descriptor{1}{"Dump"})
21380 {
21381 if(not $CheckHeadersOnly) {
21382 readLibs(1);
21383 }
21384 if($CheckHeadersOnly) {
21385 setLanguage(1, "C++");
21386 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021387 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021388 searchForHeaders(1);
21389 }
21390 $WORD_SIZE{1} = detectWordSize();
21391 }
21392 if(not $Descriptor{2}{"Dump"})
21393 {
21394 if(not $CheckHeadersOnly) {
21395 readLibs(2);
21396 }
21397 if($CheckHeadersOnly) {
21398 setLanguage(2, "C++");
21399 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021400 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021401 searchForHeaders(2);
21402 }
21403 $WORD_SIZE{2} = detectWordSize();
21404 }
21405 if($WORD_SIZE{1} ne $WORD_SIZE{2})
21406 { # support for old ABI dumps
21407 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021408 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021409 {
21410 $WORD_SIZE{1} = $WORD_SIZE{2};
21411 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
21412 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021413 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021414 {
21415 $WORD_SIZE{2} = $WORD_SIZE{1};
21416 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
21417 }
21418 }
21419 elsif(not $WORD_SIZE{1}
21420 and not $WORD_SIZE{2})
21421 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021422 $WORD_SIZE{1} = "4";
21423 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021424 }
21425 if($Descriptor{1}{"Dump"})
21426 { # support for old ABI dumps
21427 prepareTypes(1);
21428 }
21429 if($Descriptor{2}{"Dump"})
21430 { # support for old ABI dumps
21431 prepareTypes(2);
21432 }
21433 if($AppPath and not keys(%{$Symbol_Library{1}})) {
21434 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
21435 }
21436 # started to process input data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021437 if(not $CheckObjectsOnly)
21438 {
21439 if($Descriptor{1}{"Headers"}
21440 and not $Descriptor{1}{"Dump"}) {
21441 readHeaders(1);
21442 }
21443 if($Descriptor{2}{"Headers"}
21444 and not $Descriptor{2}{"Dump"}) {
21445 readHeaders(2);
21446 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021447 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021448
21449 # clean memory
21450 %SystemHeaders = ();
21451 %mangled_name_gcc = ();
21452
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021453 prepareSymbols(1);
21454 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021455
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021456 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021457 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021458
21459 # Virtual Tables
21460 registerVTable(1);
21461 registerVTable(2);
21462
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021463 if(not checkDump(1, "1.22")
21464 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021465 { # support for old ABI dumps
21466 foreach my $ClassName (keys(%{$VirtualTable{2}}))
21467 {
21468 if($ClassName=~/</)
21469 { # templates
21470 if(not defined $VirtualTable{1}{$ClassName})
21471 { # synchronize
21472 delete($VirtualTable{2}{$ClassName});
21473 }
21474 }
21475 }
21476 }
21477
21478 registerOverriding(1);
21479 registerOverriding(2);
21480
21481 setVirtFuncPositions(1);
21482 setVirtFuncPositions(2);
21483
21484 # Other
21485 addParamNames(1);
21486 addParamNames(2);
21487
21488 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021489}
21490
21491sub compareAPIs($)
21492{
21493 my $Level = $_[0];
21494 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021495 loadModule("CallConv");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021496 if($Level eq "Binary") {
21497 printMsg("INFO", "comparing ABIs ...");
21498 }
21499 else {
21500 printMsg("INFO", "comparing APIs ...");
21501 }
21502 if($CheckHeadersOnly
21503 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021504 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021505 detectAdded_H($Level);
21506 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021507 }
21508 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021509 { # added/removed in libs
21510 detectAdded($Level);
21511 detectRemoved($Level);
21512 }
21513 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021514 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021515 mergeSymbols($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021516 if(keys(%{$CheckedSymbols{$Level}})) {
21517 mergeConstants($Level);
21518 }
21519 }
21520 if($CheckHeadersOnly
21521 or $Level eq "Source")
21522 { # added/removed in headers
21523 mergeHeaders($Level);
21524 }
21525 else
21526 { # added/removed in libs
21527 mergeLibs($Level);
21528 if($CheckImpl
21529 and $Level eq "Binary") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021530 mergeImpl();
21531 }
21532 }
21533}
21534
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021535sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021536{
21537 my %Opts = (
21538 "OStarget"=>$OStarget,
21539 "Debug"=>$Debug,
21540 "Quiet"=>$Quiet,
21541 "LogMode"=>$LogMode,
21542 "CheckHeadersOnly"=>$CheckHeadersOnly,
21543
21544 "SystemRoot"=>$SystemRoot,
21545 "MODULES_DIR"=>$MODULES_DIR,
21546 "GCC_PATH"=>$GCC_PATH,
21547 "TargetSysInfo"=>$TargetSysInfo,
21548 "CrossPrefix"=>$CrossPrefix,
21549 "TargetLibraryName"=>$TargetLibraryName,
21550 "CrossGcc"=>$CrossGcc,
21551 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021552 "NoStdInc"=>$NoStdInc,
21553
21554 "BinaryOnly" => $BinaryOnly,
21555 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021556 );
21557 return \%Opts;
21558}
21559
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021560sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021561{
21562 my %CODE_ERROR = reverse(%ERROR_CODE);
21563 return $CODE_ERROR{$_[0]};
21564}
21565
21566sub scenario()
21567{
21568 if($StdOut)
21569 { # enable quiet mode
21570 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021571 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021572 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021573 if(not $LogMode)
21574 { # default
21575 $LogMode = "w";
21576 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021577 if($UserLang)
21578 { # --lang=C++
21579 $UserLang = uc($UserLang);
21580 $COMMON_LANGUAGE{1}=$UserLang;
21581 $COMMON_LANGUAGE{2}=$UserLang;
21582 }
21583 if($LoggingPath)
21584 {
21585 $OutputLogPath{1} = $LoggingPath;
21586 $OutputLogPath{2} = $LoggingPath;
21587 if($Quiet) {
21588 $COMMON_LOG_PATH = $LoggingPath;
21589 }
21590 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021591 if($OutputDumpPath)
21592 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021593 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021594 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
21595 }
21596 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021597 if($BinaryOnly and $SourceOnly)
21598 { # both --binary and --source
21599 # is the default mode
21600 $DoubleReport = 1;
21601 $JoinReport = 0;
21602 $BinaryOnly = 0;
21603 $SourceOnly = 0;
21604 if($OutputReportPath)
21605 { # --report-path
21606 $DoubleReport = 0;
21607 $JoinReport = 1;
21608 }
21609 }
21610 elsif($BinaryOnly or $SourceOnly)
21611 { # --binary or --source
21612 $DoubleReport = 0;
21613 $JoinReport = 0;
21614 }
21615 if($UseXML)
21616 { # --xml option
21617 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021618 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021619 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021620 if($ReportFormat)
21621 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021622 $ReportFormat = lc($ReportFormat);
21623 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021624 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021625 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021626 if($ReportFormat eq "htm")
21627 { # HTM == HTML
21628 $ReportFormat = "html";
21629 }
21630 elsif($ReportFormat eq "xml")
21631 { # --report-format=XML equal to --xml
21632 $UseXML = 1;
21633 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021634 }
21635 else
21636 { # default: HTML
21637 $ReportFormat = "html";
21638 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021639 if($DumpFormat)
21640 { # validate
21641 $DumpFormat = lc($DumpFormat);
21642 if($DumpFormat!~/\A(xml|perl)\Z/) {
21643 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
21644 }
21645 if($DumpFormat eq "xml")
21646 { # --dump-format=XML equal to --xml
21647 $UseXML = 1;
21648 }
21649 }
21650 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021651 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021652 $DumpFormat = "perl";
21653 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021654 if($Quiet and $LogMode!~/a|n/)
21655 { # --quiet log
21656 if(-f $COMMON_LOG_PATH) {
21657 unlink($COMMON_LOG_PATH);
21658 }
21659 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040021660 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021661 $CheckUndefined = 1;
21662 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021663 if($TestTool and $UseDumps)
21664 { # --test && --use-dumps == --test-dump
21665 $TestDump = 1;
21666 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021667 if($Tolerant)
21668 { # enable all
21669 $Tolerance = 1234;
21670 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021671 if($Help)
21672 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021673 HELP_MESSAGE();
21674 exit(0);
21675 }
21676 if($InfoMsg) {
21677 INFO_MESSAGE();
21678 exit(0);
21679 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021680 if($ShowVersion)
21681 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021682 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.");
21683 exit(0);
21684 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021685 if($DumpVersion)
21686 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021687 printMsg("INFO", $TOOL_VERSION);
21688 exit(0);
21689 }
21690 if($ExtendedCheck) {
21691 $CheckHeadersOnly = 1;
21692 }
21693 if($SystemRoot_Opt)
21694 { # user defined root
21695 if(not -e $SystemRoot_Opt) {
21696 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
21697 }
21698 $SystemRoot = $SystemRoot_Opt;
21699 $SystemRoot=~s/[\/]+\Z//g;
21700 if($SystemRoot) {
21701 $SystemRoot = get_abs_path($SystemRoot);
21702 }
21703 }
21704 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021705
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021706 if($SortDump)
21707 {
21708 $Data::Dumper::Useperl = 1;
21709 $Data::Dumper::Sortkeys = \&dump_sorting;
21710 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021711
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021712 if($TargetLibsPath)
21713 {
21714 if(not -f $TargetLibsPath) {
21715 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
21716 }
21717 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
21718 $TargetLibs{$Lib} = 1;
21719 }
21720 }
21721 if($TargetHeadersPath)
21722 { # --headers-list
21723 if(not -f $TargetHeadersPath) {
21724 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
21725 }
21726 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
21727 {
21728 $TargetHeaders{1}{$Header} = 1;
21729 $TargetHeaders{2}{$Header} = 1;
21730 }
21731 }
21732 if($TargetHeader)
21733 { # --header
21734 $TargetHeaders{1}{$TargetHeader} = 1;
21735 $TargetHeaders{2}{$TargetHeader} = 1;
21736 }
21737 if($TestTool
21738 or $TestDump)
21739 { # --test, --test-dump
21740 detect_default_paths("bin|gcc"); # to compile libs
21741 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021742 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
21743 $LIB_EXT, $GCC_PATH, $Browse, $OpenReport, $SortDump, $CheckHeadersOnly, $CheckObjectsOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021744 exit(0);
21745 }
21746 if($DumpSystem)
21747 { # --dump-system
21748 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021749 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021750 { # system XML descriptor
21751 if(not -f $DumpSystem) {
21752 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
21753 }
21754 my $Ret = readSystemDescriptor(readFile($DumpSystem));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021755 foreach (@{$Ret->{"Tools"}})
21756 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021757 push_U($SystemPaths{"bin"}, $_);
21758 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021759 }
21760 if($Ret->{"CrossPrefix"}) {
21761 $CrossPrefix = $Ret->{"CrossPrefix"};
21762 }
21763 }
21764 elsif($SystemRoot_Opt)
21765 { # -sysroot "/" option
21766 # default target: /usr/lib, /usr/include
21767 # search libs: /usr/lib and /lib
21768 if(not -e $SystemRoot."/usr/lib") {
21769 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
21770 }
21771 if(not -e $SystemRoot."/lib") {
21772 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
21773 }
21774 if(not -e $SystemRoot."/usr/include") {
21775 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
21776 }
21777 readSystemDescriptor("
21778 <name>
21779 $DumpSystem
21780 </name>
21781 <headers>
21782 $SystemRoot/usr/include
21783 </headers>
21784 <libs>
21785 $SystemRoot/usr/lib
21786 </libs>
21787 <search_libs>
21788 $SystemRoot/lib
21789 </search_libs>");
21790 }
21791 else {
21792 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
21793 }
21794 detect_default_paths("bin|gcc"); # to check symbols
21795 if($OStarget eq "windows")
21796 { # to run dumpbin.exe
21797 # and undname.exe
21798 check_win32_env();
21799 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021800 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021801 exit(0);
21802 }
21803 if($CmpSystems)
21804 { # --cmp-systems
21805 detect_default_paths("bin"); # to extract dumps
21806 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021807 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021808 exit(0);
21809 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021810 if($GenerateTemplate)
21811 {
21812 writeFile("VERSION.xml", $DescriptorTemplate."\n");
21813 printMsg("INFO", "XML-descriptor template ./VERSION.xml has been generated");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021814 exit(0);
21815 }
21816 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021817 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021818 }
21819 else
21820 { # validate library name
21821 if($TargetLibraryName=~/[\*\/\\]/) {
21822 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
21823 }
21824 }
21825 if(not $TargetLibraryFName) {
21826 $TargetLibraryFName = $TargetLibraryName;
21827 }
21828 if($CheckHeadersOnly_Opt and $CheckObjectsOnly_Opt) {
21829 exitStatus("Error", "you can't specify both -headers-only and -objects-only options at the same time");
21830 }
21831 if($SymbolsListPath)
21832 {
21833 if(not -f $SymbolsListPath) {
21834 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
21835 }
21836 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
21837 $SymbolsList{$Interface} = 1;
21838 }
21839 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021840 if($SkipSymbolsListPath)
21841 {
21842 if(not -f $SkipSymbolsListPath) {
21843 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
21844 }
21845 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath))) {
21846 $SkipSymbolsList{$Interface} = 1;
21847 }
21848 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021849 if($SkipHeadersPath)
21850 {
21851 if(not -f $SkipHeadersPath) {
21852 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
21853 }
21854 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021855 { # register for both versions
21856 $SkipHeadersList{1}{$Path} = 1;
21857 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021858 my ($CPath, $Type) = classifyPath($Path);
21859 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021860 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021861 }
21862 }
21863 if($ParamNamesPath)
21864 {
21865 if(not -f $ParamNamesPath) {
21866 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
21867 }
21868 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
21869 {
21870 if($Line=~s/\A(\w+)\;//)
21871 {
21872 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021873 if($Line=~/;(\d+);/)
21874 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021875 while($Line=~s/(\d+);(\w+)//) {
21876 $AddIntParams{$Interface}{$1}=$2;
21877 }
21878 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021879 else
21880 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021881 my $Num = 0;
21882 foreach my $Name (split(/;/, $Line)) {
21883 $AddIntParams{$Interface}{$Num++}=$Name;
21884 }
21885 }
21886 }
21887 }
21888 }
21889 if($AppPath)
21890 {
21891 if(not -f $AppPath) {
21892 exitStatus("Access_Error", "can't access file \'$AppPath\'");
21893 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021894 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021895 $SymbolsList_App{$Interface} = 1;
21896 }
21897 }
21898 if($DumpAPI)
21899 { # --dump-abi
21900 # make an API dump
21901 create_ABI_Dump();
21902 exit($COMPILE_ERRORS);
21903 }
21904 # default: compare APIs
21905 # -d1 <path>
21906 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021907 compareInit();
21908 if($JoinReport or $DoubleReport)
21909 {
21910 compareAPIs("Binary");
21911 compareAPIs("Source");
21912 }
21913 elsif($BinaryOnly) {
21914 compareAPIs("Binary");
21915 }
21916 elsif($SourceOnly) {
21917 compareAPIs("Source");
21918 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021919 exitReport();
21920}
21921
21922scenario();