blob: 305ca0b964e7741c79b66ef366ed1fcedc78fe02 [file] [log] [blame]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001#!/usr/bin/perl
2###########################################################################
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04003# ABI Compliance Checker (ACC) 1.99.7
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004# A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005#
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006# Copyright (C) 2009-2010 The Linux Foundation
7# Copyright (C) 2009-2011 Institute for System Programming, RAS
8# Copyright (C) 2011-2012 Nokia Corporation and/or its subsidiary(-ies)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009# Copyright (C) 2011-2013 ROSA Laboratory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010#
11# Written by Andrey Ponomarenko
12#
13# PLATFORMS
14# =========
15# Linux, FreeBSD, Mac OS X, Haiku, MS Windows, Symbian
16#
17# REQUIREMENTS
18# ============
19# Linux
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040020# - G++ (3.0-4.7, recommended 4.5 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021# - GNU Binutils (readelf, c++filt, objdump)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022# - Perl 5 (5.8 or newer)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040023# - Ctags (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040024#
25# Mac OS X
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040026# - Xcode (g++, c++filt, otool, nm)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040027# - Ctags (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040028#
29# MS Windows
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040030# - MinGW (3.0-4.7, recommended 4.5 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040031# - MS Visual C++ (dumpbin, undname, cl)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040032# - Active Perl 5 (5.8 or newer)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040033# - Sigcheck v1.71 or newer
34# - Info-ZIP 3.0 (zip, unzip)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040035# - Ctags (5.8 or newer)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040036# - Add tool locations to the PATH environment variable
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040037# - Run vsvars32.bat (C:\Microsoft Visual Studio 9.0\Common7\Tools\)
38#
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040039# COMPATIBILITY
40# =============
41# ABI Dumper >= 0.97
42#
43#
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040044# This program is free software: you can redistribute it and/or modify
45# it under the terms of the GNU General Public License or the GNU Lesser
46# General Public License as published by the Free Software Foundation.
47#
48# This program is distributed in the hope that it will be useful,
49# but WITHOUT ANY WARRANTY; without even the implied warranty of
50# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51# GNU General Public License for more details.
52#
53# You should have received a copy of the GNU General Public License
54# and the GNU Lesser General Public License along with this program.
55# If not, see <http://www.gnu.org/licenses/>.
56###########################################################################
57use Getopt::Long;
58Getopt::Long::Configure ("posix_default", "no_ignore_case");
59use File::Path qw(mkpath rmtree);
60use File::Temp qw(tempdir);
61use File::Copy qw(copy move);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040062use Cwd qw(abs_path cwd realpath);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040063use Storable qw(dclone);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040064use Data::Dumper;
Andrey Ponomarenko2fba6302012-03-29 17:44:47 +040065use Config;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040066
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +040067my $TOOL_VERSION = "1.99.7";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040068my $ABI_DUMP_VERSION = "3.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040069my $OLDEST_SUPPORTED_VERSION = "1.18";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040070my $XML_REPORT_VERSION = "1.1";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040071my $XML_ABI_DUMP_VERSION = "1.2";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040072my $OSgroup = get_OSgroup();
73my $ORIG_DIR = cwd();
74my $TMP_DIR = tempdir(CLEANUP=>1);
75
76# Internal modules
77my $MODULES_DIR = get_Modules();
78push(@INC, get_dirname($MODULES_DIR));
79# Rules DB
80my %RULES_PATH = (
81 "Binary" => $MODULES_DIR."/RulesBin.xml",
82 "Source" => $MODULES_DIR."/RulesSrc.xml");
83
84my ($Help, $ShowVersion, %Descriptor, $TargetLibraryName, $GenerateTemplate,
85$TestTool, $DumpAPI, $SymbolsListPath, $CheckHeadersOnly_Opt, $UseDumps,
86$CheckObjectsOnly_Opt, $AppPath, $StrictCompat, $DumpVersion, $ParamNamesPath,
87%RelativeDirectory, $TargetLibraryFName, $TestDump, $CheckImpl, $LoggingPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040088%TargetVersion, $InfoMsg, $UseOldDumps, $CrossGcc, %OutputLogPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040089$OutputReportPath, $OutputDumpPath, $ShowRetVal, $SystemRoot_Opt, $DumpSystem,
90$CmpSystems, $TargetLibsPath, $Debug, $CrossPrefix, $UseStaticLibs, $NoStdInc,
91$TargetComponent_Opt, $TargetSysInfo, $TargetHeader, $ExtendedCheck, $Quiet,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040092$SkipHeadersPath, $CppCompat, $LogMode, $StdOut, $ListAffected, $ReportFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040093$UserLang, $TargetHeadersPath, $BinaryOnly, $SourceOnly, $BinaryReportPath,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040094$SourceReportPath, $UseXML, $Browse, $OpenReport, $SortDump, $DumpFormat,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040095$ExtraInfo, $ExtraDump, $Force, $Tolerance, $Tolerant, $SkipSymbolsListPath,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040096$CheckInfo, $Quick);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040097
98my $CmdName = get_filename($0);
99my %OS_LibExt = (
100 "dynamic" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400101 "linux"=>"so",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400102 "macos"=>"dylib",
103 "windows"=>"dll",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400104 "symbian"=>"dso",
105 "default"=>"so"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400106 },
107 "static" => {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400108 "linux"=>"a",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400109 "windows"=>"lib",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +0400110 "symbian"=>"lib",
111 "default"=>"a"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400112 }
113);
114
115my %OS_Archive = (
116 "windows"=>"zip",
117 "default"=>"tar.gz"
118);
119
120my %ERROR_CODE = (
121 # Compatible verdict
122 "Compatible"=>0,
123 "Success"=>0,
124 # Incompatible verdict
125 "Incompatible"=>1,
126 # Undifferentiated error code
127 "Error"=>2,
128 # System command is not found
129 "Not_Found"=>3,
130 # Cannot access input files
131 "Access_Error"=>4,
132 # Cannot compile header files
133 "Cannot_Compile"=>5,
134 # Header compiled with errors
135 "Compile_Error"=>6,
136 # Invalid input ABI dump
137 "Invalid_Dump"=>7,
138 # Incompatible version of ABI dump
139 "Dump_Version"=>8,
140 # Cannot find a module
141 "Module_Error"=>9,
142 # Empty intersection between
143 # headers and shared objects
144 "Empty_Intersection"=>10,
145 # Empty set of symbols in headers
146 "Empty_Set"=>11
147);
148
149my %HomePage = (
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400150 "Wiki"=>"http://ispras.linuxbase.org/index.php/ABI_compliance_checker",
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400151 "Dev1"=>"https://github.com/lvc/abi-compliance-checker",
152 "Dev2"=>"http://forge.ispras.ru/projects/abi-compliance-checker"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400153);
154
155my $ShortUsage = "ABI Compliance Checker (ACC) $TOOL_VERSION
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400156A tool for checking backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400157Copyright (C) 2012 ROSA Laboratory
158License: GNU LGPL or GNU GPL
159
160Usage: $CmdName [options]
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400161Example: $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400162
163OLD.xml and NEW.xml are XML-descriptors:
164
165 <version>
166 1.0
167 </version>
168
169 <headers>
170 /path/to/headers/
171 </headers>
172
173 <libs>
174 /path/to/libraries/
175 </libs>
176
177More info: $CmdName --help\n";
178
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400179if($#ARGV==-1)
180{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400181 printMsg("INFO", $ShortUsage);
182 exit(0);
183}
184
185foreach (2 .. $#ARGV)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400186{ # correct comma separated options
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400187 if($ARGV[$_-1] eq ",")
188 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400189 $ARGV[$_-2].=",".$ARGV[$_];
190 splice(@ARGV, $_-1, 2);
191 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400192 elsif($ARGV[$_-1]=~/,\Z/)
193 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400194 $ARGV[$_-1].=$ARGV[$_];
195 splice(@ARGV, $_, 1);
196 }
197 elsif($ARGV[$_]=~/\A,/
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400198 and $ARGV[$_] ne ",")
199 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400200 $ARGV[$_-1].=$ARGV[$_];
201 splice(@ARGV, $_, 1);
202 }
203}
204
205GetOptions("h|help!" => \$Help,
206 "i|info!" => \$InfoMsg,
207 "v|version!" => \$ShowVersion,
208 "dumpversion!" => \$DumpVersion,
209# general options
210 "l|lib|library=s" => \$TargetLibraryName,
211 "d1|old|o=s" => \$Descriptor{1}{"Path"},
212 "d2|new|n=s" => \$Descriptor{2}{"Path"},
213 "dump|dump-abi|dump_abi=s" => \$DumpAPI,
214 "old-dumps!" => \$UseOldDumps,
215# extra options
216 "d|descriptor-template!" => \$GenerateTemplate,
217 "app|application=s" => \$AppPath,
218 "static-libs!" => \$UseStaticLibs,
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +0400219 "cross-gcc|gcc-path=s" => \$CrossGcc,
220 "cross-prefix|gcc-prefix=s" => \$CrossPrefix,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400221 "sysroot=s" => \$SystemRoot_Opt,
222 "v1|version1|vnum=s" => \$TargetVersion{1},
223 "v2|version2=s" => \$TargetVersion{2},
224 "s|strict!" => \$StrictCompat,
225 "symbols-list=s" => \$SymbolsListPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400226 "skip-symbols=s" => \$SkipSymbolsListPath,
227 "headers-list=s" => \$TargetHeadersPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400228 "skip-headers=s" => \$SkipHeadersPath,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400229 "header=s" => \$TargetHeader,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400230 "headers-only|headers_only!" => \$CheckHeadersOnly_Opt,
231 "objects-only!" => \$CheckObjectsOnly_Opt,
232 "check-impl|check-implementation!" => \$CheckImpl,
233 "show-retval!" => \$ShowRetVal,
234 "use-dumps!" => \$UseDumps,
235 "nostdinc!" => \$NoStdInc,
236 "dump-system=s" => \$DumpSystem,
237 "sysinfo=s" => \$TargetSysInfo,
238 "cmp-systems!" => \$CmpSystems,
239 "libs-list=s" => \$TargetLibsPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400240 "ext|extended!" => \$ExtendedCheck,
241 "q|quiet!" => \$Quiet,
242 "stdout!" => \$StdOut,
243 "report-format=s" => \$ReportFormat,
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400244 "dump-format=s" => \$DumpFormat,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400245 "xml!" => \$UseXML,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400246 "lang=s" => \$UserLang,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400247 "binary|bin|abi!" => \$BinaryOnly,
248 "source|src|api!" => \$SourceOnly,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400249# other options
250 "test!" => \$TestTool,
251 "test-dump!" => \$TestDump,
252 "debug!" => \$Debug,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400253 "cpp-compatible!" => \$CppCompat,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400254 "p|params=s" => \$ParamNamesPath,
255 "relpath1|relpath=s" => \$RelativeDirectory{1},
256 "relpath2=s" => \$RelativeDirectory{2},
257 "dump-path=s" => \$OutputDumpPath,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400258 "sort!" => \$SortDump,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400259 "report-path=s" => \$OutputReportPath,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400260 "bin-report-path=s" => \$BinaryReportPath,
261 "src-report-path=s" => \$SourceReportPath,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400262 "log-path=s" => \$LoggingPath,
263 "log1-path=s" => \$OutputLogPath{1},
264 "log2-path=s" => \$OutputLogPath{2},
265 "logging-mode=s" => \$LogMode,
266 "list-affected!" => \$ListAffected,
267 "l-full|lib-full=s" => \$TargetLibraryFName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400268 "component=s" => \$TargetComponent_Opt,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400269 "b|browse=s" => \$Browse,
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400270 "open!" => \$OpenReport,
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400271 "extra-info=s" => \$ExtraInfo,
272 "extra-dump!" => \$ExtraDump,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400273 "force!" => \$Force,
274 "tolerance=s" => \$Tolerance,
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400275 "tolerant!" => \$Tolerant,
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400276 "check!" => \$CheckInfo,
277 "quick!" => \$Quick
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400278) or ERR_MESSAGE();
279
280sub ERR_MESSAGE()
281{
282 printMsg("INFO", "\n".$ShortUsage);
283 exit($ERROR_CODE{"Error"});
284}
285
286my $LIB_TYPE = $UseStaticLibs?"static":"dynamic";
287my $SLIB_TYPE = $LIB_TYPE;
288if($OSgroup!~/macos|windows/ and $SLIB_TYPE eq "dynamic")
289{ # show as "shared" library
290 $SLIB_TYPE = "shared";
291}
292my $LIB_EXT = getLIB_EXT($OSgroup);
293my $AR_EXT = getAR_EXT($OSgroup);
294my $BYTE_SIZE = 8;
295my $COMMON_LOG_PATH = "logs/run.log";
296
297my $HelpMessage="
298NAME:
299 ABI Compliance Checker ($CmdName)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400300 Check backward compatibility of a C/C++ library API
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400301
302DESCRIPTION:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400303 ABI Compliance Checker (ACC) is a tool for checking backward binary and
304 source-level compatibility of a $SLIB_TYPE C/C++ library. The tool checks
305 header files and $SLIB_TYPE libraries (*.$LIB_EXT) of old and new versions and
306 analyzes changes in API and ABI (ABI=API+compiler ABI) that may break binary
307 and/or source-level compatibility: changes in calling stack, v-table changes,
308 removed symbols, renamed fields, etc. Binary incompatibility may result in
309 crashing or incorrect behavior of applications built with an old version of
310 a library if they run on a new one. Source incompatibility may result in
311 recompilation errors with a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400312
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +0400313 The tool is intended for developers of software libraries and maintainers
314 of operating systems who are interested in ensuring backward compatibility,
315 i.e. allow old applications to run or to be recompiled with newer library
316 versions.
317
318 Also the tool can be used by ISVs for checking applications portability to
319 new library versions. Found issues can be taken into account when adapting
320 the application to a new library version.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400321
322 This tool is free software: you can redistribute it and/or modify it
323 under the terms of the GNU LGPL or GNU GPL.
324
325USAGE:
326 $CmdName [options]
327
328EXAMPLE:
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400329 $CmdName -lib NAME -old OLD.xml -new NEW.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400330
331 OLD.xml and NEW.xml are XML-descriptors:
332
333 <version>
334 1.0
335 </version>
336
337 <headers>
338 /path1/to/header(s)/
339 /path2/to/header(s)/
340 ...
341 </headers>
342
343 <libs>
344 /path1/to/library(ies)/
345 /path2/to/library(ies)/
346 ...
347 </libs>
348
349INFORMATION OPTIONS:
350 -h|-help
351 Print this help.
352
353 -i|-info
354 Print complete info.
355
356 -v|-version
357 Print version information.
358
359 -dumpversion
360 Print the tool version ($TOOL_VERSION) and don't do anything else.
361
362GENERAL OPTIONS:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400363 -l|-lib|-library NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400364 Library name (without version).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400365
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400366 -d1|-old|-o PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400367 Descriptor of 1st (old) library version.
368 It may be one of the following:
369
370 1. XML-descriptor (VERSION.xml file):
371
372 <version>
373 1.0
374 </version>
375
376 <headers>
377 /path1/to/header(s)/
378 /path2/to/header(s)/
379 ...
380 </headers>
381
382 <libs>
383 /path1/to/library(ies)/
384 /path2/to/library(ies)/
385 ...
386 </libs>
387
388 ... (XML-descriptor template
389 can be generated by -d option)
390
391 2. ABI dump generated by -dump option
392 3. Directory with headers and/or $SLIB_TYPE libraries
393 4. Single header file
394 5. Single $SLIB_TYPE library
395 6. Comma separated list of headers and/or libraries
396
397 If you are using an 2-6 descriptor types then you should
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400398 specify version numbers with -v1 and -v2 options too.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400399
400 For more information, please see:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400401 http://ispras.linuxbase.org/index.php/Library_Descriptor
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400402
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400403 -d2|-new|-n PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400404 Descriptor of 2nd (new) library version.
405
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400406 -dump|-dump-abi PATH
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400407 Create library ABI dump for the input XML descriptor. You can
408 transfer it anywhere and pass instead of the descriptor. Also
409 it can be used for debugging the tool.
410
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400411 Supported ABI dump versions: 2.0<=V<=$ABI_DUMP_VERSION
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400412
413 -old-dumps
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400414 Enable support for old-version ABI dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0).\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400415
416sub HELP_MESSAGE() {
417 printMsg("INFO", $HelpMessage."
418MORE INFO:
419 $CmdName --info\n");
420}
421
422sub INFO_MESSAGE()
423{
424 printMsg("INFO", "$HelpMessage
425EXTRA OPTIONS:
426 -d|-descriptor-template
427 Create XML-descriptor template ./VERSION.xml
428
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400429 -app|-application PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400430 This option allows to specify the application that should be checked
431 for portability to the new library version.
432
433 -static-libs
434 Check static libraries instead of the shared ones. The <libs> section
435 of the XML-descriptor should point to static libraries location.
436
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400437 -cross-gcc|-gcc-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400438 Path to the cross GCC compiler to use instead of the usual (host) GCC.
439
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400440 -cross-prefix|-gcc-prefix PREFIX
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400441 GCC toolchain prefix.
442
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400443 -sysroot DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400444 Specify the alternative root directory. The tool will search for include
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400445 paths in the DIR/usr/include and DIR/usr/lib directories.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400446
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400447 -v1|-version1 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400448 Specify 1st library version outside the descriptor. This option is needed
449 if you have prefered an alternative descriptor type (see -d1 option).
450
451 In general case you should specify it in the XML-descriptor:
452 <version>
453 VERSION
454 </version>
455
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400456 -v2|-version2 NUM
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400457 Specify 2nd library version outside the descriptor.
458
459 -s|-strict
460 Treat all compatibility warnings as problems. Add a number of \"Low\"
461 severity problems to the return value of the tool.
462
463 -headers-only
464 Check header files without $SLIB_TYPE libraries. It is easy to run, but may
465 provide a low quality compatibility report with false positives and
466 without detecting of added/removed symbols.
467
468 Alternatively you can write \"none\" word to the <libs> section
469 in the XML-descriptor:
470 <libs>
471 none
472 </libs>
473
474 -objects-only
475 Check $SLIB_TYPE libraries without header files. It is easy to run, but may
476 provide a low quality compatibility report with false positives and
477 without analysis of changes in parameters and data types.
478
479 Alternatively you can write \"none\" word to the <headers> section
480 in the XML-descriptor:
481 <headers>
482 none
483 </headers>
484
485 -check-impl|-check-implementation
486 Compare canonified disassembled binary code of $SLIB_TYPE libraries to
487 detect changes in the implementation. Add \'Problems with Implementation\'
488 section to the report.
489
490 -show-retval
491 Show the symbol's return type in the report.
492
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400493 -symbols-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400494 This option allows to specify a file with a list of symbols (mangled
495 names in C++) that should be checked, other symbols will not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400496
497 -skip-symbols PATH
498 The list of symbols that should NOT be checked.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400499
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400500 -headers-list PATH
501 The file with a list of headers, that should be checked/dumped.
502
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400503 -skip-headers PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400504 The file with the list of header files, that should not be checked.
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +0400505
506 -header NAME
507 Check/Dump ABI of this header only.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400508
509 -use-dumps
510 Make dumps for two versions of a library and compare dumps. This should
511 increase the performance of the tool and decrease the system memory usage.
512
513 -nostdinc
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400514 Do not search in GCC standard system directories for header files.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400515
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400516 -dump-system NAME -sysroot DIR
517 Find all the shared libraries and header files in DIR directory,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400518 create XML descriptors and make ABI dumps for each library. The result
519 set of ABI dumps can be compared (--cmp-systems) with the other one
520 created for other version of operating system in order to check them for
521 compatibility. Do not forget to specify -cross-gcc option if your target
522 system requires some specific version of GCC compiler (different from
523 the host GCC). The system ABI dump will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400524 sys_dumps/NAME/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400525
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400526 -dump-system DESCRIPTOR.xml
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400527 The same as the previous option but takes an XML descriptor of the target
528 system as input, where you should describe it:
529
530 /* Primary sections */
531
532 <name>
533 /* Name of the system */
534 </name>
535
536 <headers>
537 /* The list of paths to header files and/or
538 directories with header files, one per line */
539 </headers>
540
541 <libs>
542 /* The list of paths to shared libraries and/or
543 directories with shared libraries, one per line */
544 </libs>
545
546 /* Optional sections */
547
548 <search_headers>
549 /* List of directories to be searched
550 for header files to automatically
551 generate include paths, one per line */
552 </search_headers>
553
554 <search_libs>
555 /* List of directories to be searched
556 for shared libraries to resolve
557 dependencies, one per line */
558 </search_libs>
559
560 <tools>
561 /* List of directories with tools used
562 for analysis (GCC toolchain), one per line */
563 </tools>
564
565 <cross_prefix>
566 /* GCC toolchain prefix.
567 Examples:
568 arm-linux-gnueabi
569 arm-none-symbianelf */
570 </cross_prefix>
571
572 <gcc_options>
573 /* Additional GCC options, one per line */
574 </gcc_options>
575
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400576 -sysinfo DIR
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400577 This option may be used with -dump-system to dump ABI of operating
578 systems and configure the dumping process.
579 Default:
580 modules/Targets/{unix, symbian, windows}
581
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400582 -cmp-systems -d1 sys_dumps/NAME1/ARCH -d2 sys_dumps/NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400583 Compare two system ABI dumps. Create compatibility reports for each
584 library and the common HTML report including the summary of test
585 results for all checked libraries. Report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400586 sys_compat_reports/NAME1_to_NAME2/ARCH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400587
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400588 -libs-list PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400589 The file with a list of libraries, that should be dumped by
590 the -dump-system option or should be checked by the -cmp-systems option.
591
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400592 -ext|-extended
593 If your library A is supposed to be used by other library B and you
594 want to control the ABI of B, then you should enable this option. The
595 tool will check for changes in all data types, even if they are not
596 used by any function in the library A. Such data types are not part
597 of the A library ABI, but may be a part of the ABI of the B library.
598
599 The short scheme is:
600 app C (broken) -> lib B (broken ABI) -> lib A (stable ABI)
601
602 -q|-quiet
603 Print all messages to the file instead of stdout and stderr.
604 Default path (can be changed by -log-path option):
605 $COMMON_LOG_PATH
606
607 -stdout
608 Print analysis results (compatibility reports and ABI dumps) to stdout
609 instead of creating a file. This would allow piping data to other programs.
610
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400611 -report-format FMT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400612 Change format of compatibility report.
613 Formats:
614 htm - HTML format (default)
615 xml - XML format
616
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400617 -dump-format FMT
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400618 Change format of ABI dump.
619 Formats:
620 perl - Data::Dumper format (default)
621 xml - XML format
622
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400623 -xml
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400624 Alias for: --report-format=xml or --dump-format=xml
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400625
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400626 -lang LANG
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400627 Set library language (C or C++). You can use this option if the tool
628 cannot auto-detect a language. This option may be useful for checking
629 C-library headers (--lang=C) in --headers-only or --extended modes.
630
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400631 -binary|-bin|-abi
632 Show \"Binary\" compatibility problems only.
633 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400634 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400635
636 -source|-src|-api
637 Show \"Source\" compatibility problems only.
638 Generate report to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400639 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400640
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400641OTHER OPTIONS:
642 -test
643 Run internal tests. Create two binary incompatible versions of a sample
644 library and run the tool to check them for compatibility. This option
645 allows to check if the tool works correctly in the current environment.
646
647 -test-dump
648 Test ability to create, read and compare ABI dumps.
649
650 -debug
651 Debugging mode. Print debug info on the screen. Save intermediate
652 analysis stages in the debug directory:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400653 debug/LIB_NAME/VERSION/
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400654
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400655 Also consider using --dump option for debugging the tool.
656
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400657 -cpp-compatible
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400658 If your header files are written in C language and can be compiled
659 by the G++ compiler (i.e. don't use C++ keywords), then you can tell
660 the tool about this and speedup the analysis.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400661
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400662 -p|-params PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400663 Path to file with the function parameter names. It can be used
664 for improving report view if the library header files have no
665 parameter names. File format:
666
667 func1;param1;param2;param3 ...
668 func2;param1;param2;param3 ...
669 ...
670
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400671 -relpath PATH
672 Replace {RELPATH} macros to PATH in the XML-descriptor used
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400673 for dumping the library ABI (see -dump option).
674
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400675 -relpath1 PATH
676 Replace {RELPATH} macros to PATH in the 1st XML-descriptor (-d1).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400677
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400678 -relpath2 PATH
679 Replace {RELPATH} macros to PATH in the 2nd XML-descriptor (-d2).
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400680
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400681 -dump-path PATH
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +0400682 Specify a *.abi.$AR_EXT or *.abi file path where to generate an ABI dump.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400683 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400684 abi_dumps/LIB_NAME/LIB_NAME_VERSION.abi.$AR_EXT
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400685
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400686 -sort
687 Enable sorting of data in ABI dumps.
688
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400689 -report-path PATH
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +0400690 Path to compatibility report.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400691 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400692 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400693
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400694 -bin-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400695 Path to \"Binary\" compatibility report.
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400696 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400697 compat_reports/LIB_NAME/V1_to_V2/abi_compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400698
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400699 -src-report-path PATH
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400700 Path to \"Source\" compatibility report.
701 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400702 compat_reports/LIB_NAME/V1_to_V2/src_compat_report.html
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400703
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400704 -log-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400705 Log path for all messages.
706 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400707 logs/LIB_NAME/VERSION/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400708
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400709 -log1-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400710 Log path for 1st version of a library.
711 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400712 logs/LIB_NAME/V1/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400713
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400714 -log2-path PATH
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400715 Log path for 2nd version of a library.
716 Default:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400717 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400718
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400719 -logging-mode MODE
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400720 Change logging mode.
721 Modes:
722 w - overwrite old logs (default)
723 a - append old logs
724 n - do not write any logs
725
726 -list-affected
727 Generate file with the list of incompatible
728 symbols beside the HTML compatibility report.
729 Use 'c++filt \@file' command from GNU binutils
730 to unmangle C++ symbols in the generated file.
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400731 Default names:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400732 abi_affected.txt
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400733 src_affected.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400734
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400735 -component NAME
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400736 The component name in the title and summary of the HTML report.
737 Default:
738 library
739
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400740 -l-full|-lib-full NAME
741 Change library name in the report title to NAME. By default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400742 will be displayed a name specified by -l option.
743
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400744 -b|-browse PROGRAM
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400745 Open report(s) in the browser (firefox, opera, etc.).
746
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400747 -open
748 Open report(s) in the default browser.
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400749
750 -extra-info DIR
751 Dump extra info to DIR.
Andrey Ponomarenko570ece52012-11-30 16:36:44 +0400752
753 -extra-dump
754 Create extended ABI dump containing all symbols
755 from the translation unit.
756
757 -force
758 Try to use this option if the tool doesn't work.
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +0400759
760 -tolerance LEVEL
761 Apply a set of heuristics to successfully compile input
762 header files. You can enable several tolerance levels by
763 joining them into one string (e.g. 13, 124, etc.).
764 Levels:
765 1 - skip non-Linux headers (e.g. win32_*.h, etc.)
766 2 - skip internal headers (e.g. *_p.h, impl/*.h, etc.)
767 3 - skip headers that iclude non-Linux headers
768 4 - skip headers included by others
769
770 -tolerant
771 Enable highest tolerance level [1234].
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400772
773 -check
774 Check completeness of the ABI dump.
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +0400775
776 -quick
777 Quick analysis. Disable check of some template instances.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400778
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400779REPORT:
780 Compatibility report will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400781 compat_reports/LIB_NAME/V1_to_V2/compat_report.html
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400782
783 Log will be generated to:
Andrey Ponomarenko07aea072012-11-12 16:15:07 +0400784 logs/LIB_NAME/V1/log.txt
785 logs/LIB_NAME/V2/log.txt
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400786
787EXIT CODES:
788 0 - Compatible. The tool has run without any errors.
789 non-zero - Incompatible or the tool has run with errors.
790
791REPORT BUGS TO:
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400792 Andrey Ponomarenko <aponomarenko\@rosalab.ru>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400793
794MORE INFORMATION:
795 ".$HomePage{"Wiki"}."
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +0400796 ".$HomePage{"Dev1"}."\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400797}
798
799my $DescriptorTemplate = "
800<?xml version=\"1.0\" encoding=\"utf-8\"?>
801<descriptor>
802
803/* Primary sections */
804
805<version>
806 /* Version of the library */
807</version>
808
809<headers>
810 /* The list of paths to header files and/or
811 directories with header files, one per line */
812</headers>
813
814<libs>
815 /* The list of paths to shared libraries (*.$LIB_EXT) and/or
816 directories with shared libraries, one per line */
817</libs>
818
819/* Optional sections */
820
821<include_paths>
822 /* The list of include paths that will be provided
823 to GCC to compile library headers, one per line.
824 NOTE: If you define this section then the tool
825 will not automatically generate include paths */
826</include_paths>
827
828<add_include_paths>
829 /* The list of include paths that will be added
830 to the automatically generated include paths, one per line */
831</add_include_paths>
832
833<skip_include_paths>
834 /* The list of include paths that will be removed from the
835 list of automatically generated include paths, one per line */
836</skip_include_paths>
837
838<gcc_options>
839 /* Additional GCC options, one per line */
840</gcc_options>
841
842<include_preamble>
843 /* The list of header files that will be
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +0400844 included before other headers, one per line */
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400845</include_preamble>
846
847<defines>
848 /* The list of defines that will be added at the
849 headers compiling stage, one per line:
850 #define A B
851 #define C D */
852</defines>
853
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +0400854<add_namespaces>
855 /* The list of namespaces that should be added to the alanysis
856 if the tool cannot find them automatically, one per line */
857</add_namespaces>
858
Andrey Ponomarenkoab282102012-03-11 11:57:02 +0400859<skip_types>
860 /* The list of data types, that
861 should not be checked, one per line */
862</skip_types>
863
864<skip_symbols>
865 /* The list of functions (mangled/symbol names in C++),
866 that should not be checked, one per line */
867</skip_symbols>
868
869<skip_namespaces>
870 /* The list of C++ namespaces, that
871 should not be checked, one per line */
872</skip_namespaces>
873
874<skip_constants>
875 /* The list of constants that should
876 not be checked, one name per line */
877</skip_constants>
878
879<skip_headers>
880 /* The list of header files and/or directories
881 with header files that should not be checked, one per line */
882</skip_headers>
883
884<skip_libs>
885 /* The list of shared libraries and/or directories
886 with shared libraries that should not be checked, one per line */
887</skip_libs>
888
889<skip_including>
890 /* The list of header files, that cannot be included
891 directly (or non-self compiled ones), one per line */
892</skip_including>
893
894<search_headers>
895 /* List of directories to be searched
896 for header files to automatically
897 generate include paths, one per line. */
898</search_headers>
899
900<search_libs>
901 /* List of directories to be searched
902 for shared librariess to resolve
903 dependencies, one per line */
904</search_libs>
905
906<tools>
907 /* List of directories with tools used
908 for analysis (GCC toolchain), one per line */
909</tools>
910
911<cross_prefix>
912 /* GCC toolchain prefix.
913 Examples:
914 arm-linux-gnueabi
915 arm-none-symbianelf */
916</cross_prefix>
917
918</descriptor>";
919
920my %Operator_Indication = (
921 "not" => "~",
922 "assign" => "=",
923 "andassign" => "&=",
924 "orassign" => "|=",
925 "xorassign" => "^=",
926 "or" => "|",
927 "xor" => "^",
928 "addr" => "&",
929 "and" => "&",
930 "lnot" => "!",
931 "eq" => "==",
932 "ne" => "!=",
933 "lt" => "<",
934 "lshift" => "<<",
935 "lshiftassign" => "<<=",
936 "rshiftassign" => ">>=",
937 "call" => "()",
938 "mod" => "%",
939 "modassign" => "%=",
940 "subs" => "[]",
941 "land" => "&&",
942 "lor" => "||",
943 "rshift" => ">>",
944 "ref" => "->",
945 "le" => "<=",
946 "deref" => "*",
947 "mult" => "*",
948 "preinc" => "++",
949 "delete" => " delete",
950 "vecnew" => " new[]",
951 "vecdelete" => " delete[]",
952 "predec" => "--",
953 "postinc" => "++",
954 "postdec" => "--",
955 "plusassign" => "+=",
956 "plus" => "+",
957 "minus" => "-",
958 "minusassign" => "-=",
959 "gt" => ">",
960 "ge" => ">=",
961 "new" => " new",
962 "multassign" => "*=",
963 "divassign" => "/=",
964 "div" => "/",
965 "neg" => "-",
966 "pos" => "+",
967 "memref" => "->*",
968 "compound" => "," );
969
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400970my %UnknownOperator;
971
972my %NodeType= (
973 "array_type" => "Array",
974 "binfo" => "Other",
975 "boolean_type" => "Intrinsic",
976 "complex_type" => "Intrinsic",
977 "const_decl" => "Other",
978 "enumeral_type" => "Enum",
979 "field_decl" => "Other",
980 "function_decl" => "Other",
981 "function_type" => "FunctionType",
982 "identifier_node" => "Other",
983 "integer_cst" => "Other",
984 "integer_type" => "Intrinsic",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400985 "vector_type" => "Vector",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400986 "method_type" => "MethodType",
987 "namespace_decl" => "Other",
988 "parm_decl" => "Other",
989 "pointer_type" => "Pointer",
990 "real_cst" => "Other",
991 "real_type" => "Intrinsic",
992 "record_type" => "Struct",
993 "reference_type" => "Ref",
994 "string_cst" => "Other",
995 "template_decl" => "Other",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +0400996 "template_type_parm" => "TemplateParam",
997 "typename_type" => "TypeName",
998 "sizeof_expr" => "SizeOf",
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +0400999 "tree_list" => "Other",
1000 "tree_vec" => "Other",
1001 "type_decl" => "Other",
1002 "union_type" => "Union",
1003 "var_decl" => "Other",
1004 "void_type" => "Intrinsic",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001005 "nop_expr" => "Other", #
1006 "addr_expr" => "Other", #
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001007 "offset_type" => "Other" );
1008
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001009my %CppKeywords_C = map {$_=>1} (
1010 # C++ 2003 keywords
1011 "public",
1012 "protected",
1013 "private",
1014 "default",
1015 "template",
1016 "new",
1017 #"asm",
1018 "dynamic_cast",
1019 "auto",
1020 "try",
1021 "namespace",
1022 "typename",
1023 "using",
1024 "reinterpret_cast",
1025 "friend",
1026 "class",
1027 "virtual",
1028 "const_cast",
1029 "mutable",
1030 "static_cast",
1031 "export",
1032 # C++0x keywords
1033 "noexcept",
1034 "nullptr",
1035 "constexpr",
1036 "static_assert",
1037 "explicit",
1038 # cannot be used as a macro name
1039 # as it is an operator in C++
1040 "and",
1041 #"and_eq",
1042 "not",
1043 #"not_eq",
1044 "or"
1045 #"or_eq",
1046 #"bitand",
1047 #"bitor",
1048 #"xor",
1049 #"xor_eq",
1050 #"compl"
1051);
1052
1053my %CppKeywords_F = map {$_=>1} (
1054 "delete",
1055 "catch",
1056 "alignof",
1057 "thread_local",
1058 "decltype",
1059 "typeid"
1060);
1061
1062my %CppKeywords_O = map {$_=>1} (
1063 "bool",
1064 "register",
1065 "inline",
1066 "operator"
1067);
1068
1069my %CppKeywords_A = map {$_=>1} (
1070 "this",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001071 "throw",
1072 "template"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001073);
1074
1075foreach (keys(%CppKeywords_C),
1076keys(%CppKeywords_F),
1077keys(%CppKeywords_O)) {
1078 $CppKeywords_A{$_}=1;
1079}
1080
1081# Header file extensions as described by gcc
1082my $HEADER_EXT = "h|hh|hp|hxx|hpp|h\\+\\+";
1083
1084my %IntrinsicMangling = (
1085 "void" => "v",
1086 "bool" => "b",
1087 "wchar_t" => "w",
1088 "char" => "c",
1089 "signed char" => "a",
1090 "unsigned char" => "h",
1091 "short" => "s",
1092 "unsigned short" => "t",
1093 "int" => "i",
1094 "unsigned int" => "j",
1095 "long" => "l",
1096 "unsigned long" => "m",
1097 "long long" => "x",
1098 "__int64" => "x",
1099 "unsigned long long" => "y",
1100 "__int128" => "n",
1101 "unsigned __int128" => "o",
1102 "float" => "f",
1103 "double" => "d",
1104 "long double" => "e",
1105 "__float80" => "e",
1106 "__float128" => "g",
1107 "..." => "z"
1108);
1109
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001110my %IntrinsicNames = map {$_=>1} keys(%IntrinsicMangling);
1111
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001112my %StdcxxMangling = (
1113 "3std"=>"St",
1114 "3std9allocator"=>"Sa",
1115 "3std12basic_string"=>"Sb",
1116 "3std12basic_stringIcE"=>"Ss",
1117 "3std13basic_istreamIcE"=>"Si",
1118 "3std13basic_ostreamIcE"=>"So",
1119 "3std14basic_iostreamIcE"=>"Sd"
1120);
1121
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04001122my $DEFAULT_STD_PARMS = "std::(allocator|less|char_traits|regex_traits|istreambuf_iterator|ostreambuf_iterator)";
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001123my %DEFAULT_STD_ARGS = map {$_=>1} ("_Alloc", "_Compare", "_Traits", "_Rx_traits", "_InIter", "_OutIter");
1124
1125my $ADD_TMPL_INSTANCES = 1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001126
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001127my %ConstantSuffix = (
1128 "unsigned int"=>"u",
1129 "long"=>"l",
1130 "unsigned long"=>"ul",
1131 "long long"=>"ll",
1132 "unsigned long long"=>"ull"
1133);
1134
1135my %ConstantSuffixR =
1136reverse(%ConstantSuffix);
1137
1138my %OperatorMangling = (
1139 "~" => "co",
1140 "=" => "aS",
1141 "|" => "or",
1142 "^" => "eo",
1143 "&" => "an",#ad (addr)
1144 "==" => "eq",
1145 "!" => "nt",
1146 "!=" => "ne",
1147 "<" => "lt",
1148 "<=" => "le",
1149 "<<" => "ls",
1150 "<<=" => "lS",
1151 ">" => "gt",
1152 ">=" => "ge",
1153 ">>" => "rs",
1154 ">>=" => "rS",
1155 "()" => "cl",
1156 "%" => "rm",
1157 "[]" => "ix",
1158 "&&" => "aa",
1159 "||" => "oo",
1160 "*" => "ml",#de (deref)
1161 "++" => "pp",#
1162 "--" => "mm",#
1163 "new" => "nw",
1164 "delete" => "dl",
1165 "new[]" => "na",
1166 "delete[]" => "da",
1167 "+=" => "pL",
1168 "+" => "pl",#ps (pos)
1169 "-" => "mi",#ng (neg)
1170 "-=" => "mI",
1171 "*=" => "mL",
1172 "/=" => "dV",
1173 "&=" => "aN",
1174 "|=" => "oR",
1175 "%=" => "rM",
1176 "^=" => "eO",
1177 "/" => "dv",
1178 "->*" => "pm",
1179 "->" => "pt",#rf (ref)
1180 "," => "cm",
1181 "?" => "qu",
1182 "." => "dt",
1183 "sizeof"=> "sz"#st
1184);
1185
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001186my %Intrinsic_Keywords = map {$_=>1} (
1187 "true",
1188 "false",
1189 "_Bool",
1190 "_Complex",
1191 "const",
1192 "int",
1193 "long",
1194 "void",
1195 "short",
1196 "float",
1197 "volatile",
1198 "restrict",
1199 "unsigned",
1200 "signed",
1201 "char",
1202 "double",
1203 "class",
1204 "struct",
1205 "union",
1206 "enum"
1207);
1208
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001209my %GlibcHeader = map {$_=>1} (
1210 "aliases.h",
1211 "argp.h",
1212 "argz.h",
1213 "assert.h",
1214 "cpio.h",
1215 "ctype.h",
1216 "dirent.h",
1217 "envz.h",
1218 "errno.h",
1219 "error.h",
1220 "execinfo.h",
1221 "fcntl.h",
1222 "fstab.h",
1223 "ftw.h",
1224 "glob.h",
1225 "grp.h",
1226 "iconv.h",
1227 "ifaddrs.h",
1228 "inttypes.h",
1229 "langinfo.h",
1230 "limits.h",
1231 "link.h",
1232 "locale.h",
1233 "malloc.h",
1234 "math.h",
1235 "mntent.h",
1236 "monetary.h",
1237 "nl_types.h",
1238 "obstack.h",
1239 "printf.h",
1240 "pwd.h",
1241 "regex.h",
1242 "sched.h",
1243 "search.h",
1244 "setjmp.h",
1245 "shadow.h",
1246 "signal.h",
1247 "spawn.h",
1248 "stdarg.h",
1249 "stdint.h",
1250 "stdio.h",
1251 "stdlib.h",
1252 "string.h",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001253 "strings.h",
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001254 "tar.h",
1255 "termios.h",
1256 "time.h",
1257 "ulimit.h",
1258 "unistd.h",
1259 "utime.h",
1260 "wchar.h",
1261 "wctype.h",
1262 "wordexp.h" );
1263
1264my %GlibcDir = map {$_=>1} (
1265 "arpa",
1266 "bits",
1267 "gnu",
1268 "netinet",
1269 "net",
1270 "nfs",
1271 "rpc",
1272 "sys",
1273 "linux" );
1274
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001275my %WinHeaders = map {$_=>1} (
1276 "dos.h",
1277 "process.h",
1278 "winsock.h",
1279 "config-win.h",
1280 "mem.h",
1281 "windows.h",
1282 "winsock2.h",
1283 "crtdbg.h",
1284 "ws2tcpip.h"
1285);
1286
1287my %ObsoleteHeaders = map {$_=>1} (
1288 "iostream.h",
1289 "fstream.h"
1290);
1291
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001292my %AlienHeaders = map {$_=>1} (
1293 # Solaris
1294 "thread.h",
1295 "sys/atomic.h",
1296 # HPUX
1297 "sys/stream.h",
1298 # Symbian
1299 "AknDoc.h",
1300 # Atari ST
1301 "ext.h",
1302 "tos.h",
1303 # MS-DOS
1304 "alloc.h",
1305 # Sparc
1306 "sys/atomic.h"
1307);
1308
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001309my %ConfHeaders = map {$_=>1} (
1310 "atomic",
1311 "conf.h",
1312 "config.h",
1313 "configure.h",
1314 "build.h",
1315 "setup.h"
1316);
1317
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001318my %LocalIncludes = map {$_=>1} (
1319 "/usr/local/include",
1320 "/usr/local" );
1321
1322my %OS_AddPath=(
1323# These paths are needed if the tool cannot detect them automatically
1324 "macos"=>{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001325 "include"=>[
1326 "/Library",
1327 "/Developer/usr/include"
1328 ],
1329 "lib"=>[
1330 "/Library",
1331 "/Developer/usr/lib"
1332 ],
1333 "bin"=>[
1334 "/Developer/usr/bin"
1335 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001336 },
1337 "beos"=>{
1338 # Haiku has GCC 2.95.3 by default
1339 # try to find GCC>=3.0 in /boot/develop/abi
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001340 "include"=>[
1341 "/boot/common",
1342 "/boot/develop"
1343 ],
1344 "lib"=>[
1345 "/boot/common/lib",
1346 "/boot/system/lib",
1347 "/boot/apps"
1348 ],
1349 "bin"=>[
1350 "/boot/common/bin",
1351 "/boot/system/bin",
1352 "/boot/develop/abi"
1353 ]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001354 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001355);
1356
1357my %Slash_Type=(
1358 "default"=>"/",
1359 "windows"=>"\\"
1360);
1361
1362my $SLASH = $Slash_Type{$OSgroup}?$Slash_Type{$OSgroup}:$Slash_Type{"default"};
1363
1364# Global Variables
1365my %COMMON_LANGUAGE=(
1366 1 => "C",
1367 2 => "C" );
1368
1369my $MAX_COMMAND_LINE_ARGUMENTS = 4096;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001370my $MAX_CPPFILT_FILE_SIZE = 50000;
1371my $CPPFILT_SUPPORT_FILE;
1372
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001373my (%WORD_SIZE, %CPU_ARCH, %GCC_VERSION);
1374
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001375my $STDCXX_TESTING = 0;
1376my $GLIBC_TESTING = 0;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001377my $CPP_HEADERS = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001378
1379my $CheckHeadersOnly = $CheckHeadersOnly_Opt;
1380my $CheckObjectsOnly = $CheckObjectsOnly_Opt;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001381
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001382my $TargetComponent;
1383
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001384my $CheckUndefined = 0;
1385
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001386# Set Target Component Name
1387if($TargetComponent_Opt) {
1388 $TargetComponent = lc($TargetComponent_Opt);
1389}
1390else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001391{ # default: library
1392 # other components: header, system, ...
1393 $TargetComponent = "library";
1394}
1395
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001396my $TOP_REF = "<a style='font-size:11px;' href='#Top'>to the top</a>";
1397
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001398my $SystemRoot;
1399
1400my $MAIN_CPP_DIR;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001401my %RESULT;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001402my %LOG_PATH;
1403my %DEBUG_PATH;
1404my %Cache;
1405my %LibInfo;
1406my $COMPILE_ERRORS = 0;
1407my %CompilerOptions;
1408my %CheckedDyLib;
1409my $TargetLibraryShortName = parse_libname($TargetLibraryName, "shortest", $OSgroup);
1410
1411# Constants (#defines)
1412my %Constants;
1413my %SkipConstants;
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04001414my %EnumConstants;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001415
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001416# Extra Info
1417my %SymbolHeader;
1418my %KnownLibs;
1419
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001420# Templates
1421my %TemplateInstance;
1422my %BasicTemplate;
1423my %TemplateArg;
1424my %TemplateDecl;
1425my %TemplateMap;
1426
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001427# Types
1428my %TypeInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001429my %SkipTypes = (
1430 "1"=>{},
1431 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001432my %CheckedTypes;
1433my %TName_Tid;
1434my %EnumMembName_Id;
1435my %NestedNameSpaces = (
1436 "1"=>{},
1437 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001438my %VirtualTable;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001439my %VirtualTable_Model;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001440my %ClassVTable;
1441my %ClassVTable_Content;
1442my %VTableClass;
1443my %AllocableClass;
1444my %ClassMethods;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001445my %ClassNames;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001446my %Class_SubClasses;
1447my %OverriddenMethods;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04001448my %TypedefToAnon;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001449my $MAX_ID = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001450
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04001451my %CheckedTypeInfo;
1452
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001453# Typedefs
1454my %Typedef_BaseName;
1455my %Typedef_Tr;
1456my %Typedef_Eq;
1457my %StdCxxTypedef;
1458my %MissedTypedef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001459my %MissedBase;
1460my %MissedBase_R;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001461my %TypeTypedef;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001462
1463# Symbols
1464my %SymbolInfo;
1465my %tr_name;
1466my %mangled_name_gcc;
1467my %mangled_name;
1468my %SkipSymbols = (
1469 "1"=>{},
1470 "2"=>{} );
1471my %SkipNameSpaces = (
1472 "1"=>{},
1473 "2"=>{} );
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001474my %AddNameSpaces = (
1475 "1"=>{},
1476 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001477my %SymbolsList;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001478my %SkipSymbolsList;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001479my %SymbolsList_App;
1480my %CheckedSymbols;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001481my %Symbol_Library = (
1482 "1"=>{},
1483 "2"=>{} );
1484my %Library_Symbol = (
1485 "1"=>{},
1486 "2"=>{} );
1487my %DepSymbol_Library = (
1488 "1"=>{},
1489 "2"=>{} );
1490my %DepLibrary_Symbol = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001491 "1"=>{},
1492 "2"=>{} );
1493my %MangledNames;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001494my %Func_ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001495my %AddIntParams;
1496my %Interface_Impl;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001497my %GlobalDataObject;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001498my %WeakSymbols;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001499my %Library_Needed= (
1500 "1"=>{},
1501 "2"=>{} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001502
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001503# Extra Info
1504my %UndefinedSymbols;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001505my %PreprocessedHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001506
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001507# Headers
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001508my %Include_Preamble = (
1509 "1"=>[],
1510 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001511my %Registered_Headers;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001512my %Registered_Sources;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001513my %HeaderName_Paths;
1514my %Header_Dependency;
1515my %Include_Neighbors;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001516my %Include_Paths = (
1517 "1"=>[],
1518 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001519my %INC_PATH_AUTODETECT = (
1520 "1"=>1,
1521 "2"=>1 );
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001522my %Add_Include_Paths = (
1523 "1"=>[],
1524 "2"=>[] );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001525my %Skip_Include_Paths;
1526my %RegisteredDirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001527my %Header_ErrorRedirect;
1528my %Header_Includes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001529my %Header_Includes_R;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001530my %Header_ShouldNotBeUsed;
1531my %RecursiveIncludes;
1532my %Header_Include_Prefix;
1533my %SkipHeaders;
1534my %SkipHeadersList=(
1535 "1"=>{},
1536 "2"=>{} );
1537my %SkipLibs;
1538my %Include_Order;
1539my %TUnit_NameSpaces;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001540my %TUnit_Classes;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001541my %TUnit_Funcs;
1542my %TUnit_Vars;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001543
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001544my %CppMode = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001545 "1"=>0,
1546 "2"=>0 );
1547my %AutoPreambleMode = (
1548 "1"=>0,
1549 "2"=>0 );
1550my %MinGWMode = (
1551 "1"=>0,
1552 "2"=>0 );
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001553my %Cpp0xMode = (
1554 "1"=>0,
1555 "2"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001556
1557# Shared Objects
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001558my %RegisteredObjects;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04001559my %RegisteredObjects_Short;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001560my %RegisteredSONAMEs;
1561my %RegisteredObject_Dirs;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001562
1563# System Objects
1564my %SystemObjects;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001565my @DefaultLibPaths;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04001566my %DyLib_DefaultPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001567
1568# System Headers
1569my %SystemHeaders;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001570my @DefaultCppPaths;
1571my @DefaultGccPaths;
1572my @DefaultIncPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001573my %DefaultCppHeader;
1574my %DefaultGccHeader;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001575my @UsersIncPath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001576
1577# Merging
1578my %CompleteSignature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001579my $Version;
1580my %AddedInt;
1581my %RemovedInt;
1582my %AddedInt_Virt;
1583my %RemovedInt_Virt;
1584my %VirtualReplacement;
1585my %ChangedTypedef;
1586my %CompatRules;
1587my %IncompleteRules;
1588my %UnknownRules;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04001589my %VTableChanged_M;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001590my %ExtendedSymbols;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001591my %ReturnedClass;
1592my %ParamClass;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001593my %SourceAlternative;
1594my %SourceAlternative_B;
1595my %SourceReplacement;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001596
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001597# Calling Conventions
1598my %UseConv_Real = (
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04001599 1=>{ "R"=>0, "P"=>0 },
1600 2=>{ "R"=>0, "P"=>0 }
1601);
1602
1603# ABI Dump
1604my %UsedDump;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04001605
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001606# OS Compliance
1607my %TargetLibs;
1608my %TargetHeaders;
1609
1610# OS Specifics
1611my $OStarget = $OSgroup;
1612my %TargetTools;
1613
1614# Compliance Report
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001615my %Type_MaxSeverity;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001616
1617# Recursion locks
1618my @RecurLib;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001619my @RecurTypes;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001620my @RecurTypes_Diff;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001621my @RecurInclude;
1622my @RecurConstant;
1623
1624# System
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001625my %SystemPaths = (
1626 "include"=>[],
1627 "lib"=>[],
1628 "bin"=>[]
1629);
1630my @DefaultBinPaths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001631my $GCC_PATH;
1632
1633# Symbols versioning
1634my %SymVer = (
1635 "1"=>{},
1636 "2"=>{} );
1637
1638# Problem descriptions
1639my %CompatProblems;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04001640my %CompatProblems_Constants;
1641my %CompatProblems_Impl;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001642my %TotalAffected;
1643
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001644# Reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001645my $ContentID = 1;
1646my $ContentSpanStart = "<span class=\"section\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1647my $ContentSpanStart_Affected = "<span class=\"section_affected\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1648my $ContentSpanStart_Info = "<span class=\"section_info\" onclick=\"javascript:showContent(this, 'CONTENT_ID')\">\n";
1649my $ContentSpanEnd = "</span>\n";
1650my $ContentDivStart = "<div id=\"CONTENT_ID\" style=\"display:none;\">\n";
1651my $ContentDivEnd = "</div>\n";
1652my $Content_Counter = 0;
1653
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001654# Modes
1655my $JoinReport = 1;
1656my $DoubleReport = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001657
1658sub get_Modules()
1659{
1660 my $TOOL_DIR = get_dirname($0);
1661 if(not $TOOL_DIR)
1662 { # patch for MS Windows
1663 $TOOL_DIR = ".";
1664 }
1665 my @SEARCH_DIRS = (
1666 # tool's directory
1667 abs_path($TOOL_DIR),
1668 # relative path to modules
1669 abs_path($TOOL_DIR)."/../share/abi-compliance-checker",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001670 # install path
1671 'MODULES_INSTALL_PATH'
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001672 );
1673 foreach my $DIR (@SEARCH_DIRS)
1674 {
1675 if(not is_abs($DIR))
1676 { # relative path
1677 $DIR = abs_path($TOOL_DIR)."/".$DIR;
1678 }
1679 if(-d $DIR."/modules") {
1680 return $DIR."/modules";
1681 }
1682 }
1683 exitStatus("Module_Error", "can't find modules");
1684}
1685
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001686my %LoadedModules = ();
1687
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001688sub loadModule($)
1689{
1690 my $Name = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001691 if(defined $LoadedModules{$Name}) {
1692 return;
1693 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001694 my $Path = $MODULES_DIR."/Internals/$Name.pm";
1695 if(not -f $Path) {
1696 exitStatus("Module_Error", "can't access \'$Path\'");
1697 }
1698 require $Path;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04001699 $LoadedModules{$Name} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001700}
1701
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001702sub readModule($$)
1703{
1704 my ($Module, $Name) = @_;
1705 my $Path = $MODULES_DIR."/Internals/$Module/".$Name;
1706 if(not -f $Path) {
1707 exitStatus("Module_Error", "can't access \'$Path\'");
1708 }
1709 return readFile($Path);
1710}
1711
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04001712sub showPos($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001713{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04001714 my $Number = $_[0];
1715 if(not $Number) {
1716 $Number = 1;
1717 }
1718 else {
1719 $Number = int($Number)+1;
1720 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001721 if($Number>3) {
1722 return $Number."th";
1723 }
1724 elsif($Number==1) {
1725 return "1st";
1726 }
1727 elsif($Number==2) {
1728 return "2nd";
1729 }
1730 elsif($Number==3) {
1731 return "3rd";
1732 }
1733 else {
1734 return $Number;
1735 }
1736}
1737
1738sub search_Tools($)
1739{
1740 my $Name = $_[0];
1741 return "" if(not $Name);
1742 if(my @Paths = keys(%TargetTools))
1743 {
1744 foreach my $Path (@Paths)
1745 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001746 if(-f join_P($Path, $Name)) {
1747 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001748 }
1749 if($CrossPrefix)
1750 { # user-defined prefix (arm-none-symbianelf, ...)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001751 my $Candidate = join_P($Path, $CrossPrefix."-".$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001752 if(-f $Candidate) {
1753 return $Candidate;
1754 }
1755 }
1756 }
1757 }
1758 else {
1759 return "";
1760 }
1761}
1762
1763sub synch_Cmd($)
1764{
1765 my $Name = $_[0];
1766 if(not $GCC_PATH)
1767 { # GCC was not found yet
1768 return "";
1769 }
1770 my $Candidate = $GCC_PATH;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001771 if($Candidate=~s/\bgcc(|\.\w+)\Z/$Name$1/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001772 return $Candidate;
1773 }
1774 return "";
1775}
1776
1777sub get_CmdPath($)
1778{
1779 my $Name = $_[0];
1780 return "" if(not $Name);
1781 if(defined $Cache{"get_CmdPath"}{$Name}) {
1782 return $Cache{"get_CmdPath"}{$Name};
1783 }
1784 my %BinUtils = map {$_=>1} (
1785 "c++filt",
1786 "objdump",
1787 "readelf"
1788 );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001789 if($BinUtils{$Name} and $GCC_PATH)
1790 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001791 if(my $Dir = get_dirname($GCC_PATH)) {
1792 $TargetTools{$Dir}=1;
1793 }
1794 }
1795 my $Path = search_Tools($Name);
1796 if(not $Path and $OSgroup eq "windows") {
1797 $Path = search_Tools($Name.".exe");
1798 }
1799 if(not $Path and $BinUtils{$Name})
1800 {
1801 if($CrossPrefix)
1802 { # user-defined prefix
1803 $Path = search_Cmd($CrossPrefix."-".$Name);
1804 }
1805 }
1806 if(not $Path and $BinUtils{$Name})
1807 {
1808 if(my $Candidate = synch_Cmd($Name))
1809 { # synch with GCC
1810 if($Candidate=~/[\/\\]/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001811 { # command path
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001812 if(-f $Candidate) {
1813 $Path = $Candidate;
1814 }
1815 }
1816 elsif($Candidate = search_Cmd($Candidate))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001817 { # command name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001818 $Path = $Candidate;
1819 }
1820 }
1821 }
1822 if(not $Path) {
1823 $Path = search_Cmd($Name);
1824 }
1825 if(not $Path and $OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04001826 { # search for *.exe file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001827 $Path=search_Cmd($Name.".exe");
1828 }
1829 if($Path=~/\s/) {
1830 $Path = "\"".$Path."\"";
1831 }
1832 return ($Cache{"get_CmdPath"}{$Name}=$Path);
1833}
1834
1835sub search_Cmd($)
1836{
1837 my $Name = $_[0];
1838 return "" if(not $Name);
1839 if(defined $Cache{"search_Cmd"}{$Name}) {
1840 return $Cache{"search_Cmd"}{$Name};
1841 }
1842 if(my $DefaultPath = get_CmdPath_Default($Name)) {
1843 return ($Cache{"search_Cmd"}{$Name} = $DefaultPath);
1844 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001845 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001846 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001847 my $CmdPath = join_P($Path,$Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001848 if(-f $CmdPath)
1849 {
1850 if($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001851 next if(not check_gcc($CmdPath, "3"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001852 }
1853 return ($Cache{"search_Cmd"}{$Name} = $CmdPath);
1854 }
1855 }
1856 return ($Cache{"search_Cmd"}{$Name} = "");
1857}
1858
1859sub get_CmdPath_Default($)
1860{ # search in PATH
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001861 return "" if(not $_[0]);
1862 if(defined $Cache{"get_CmdPath_Default"}{$_[0]}) {
1863 return $Cache{"get_CmdPath_Default"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001864 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001865 return ($Cache{"get_CmdPath_Default"}{$_[0]} = get_CmdPath_Default_I($_[0]));
1866}
1867
1868sub get_CmdPath_Default_I($)
1869{ # search in PATH
1870 my $Name = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001871 if($Name=~/find/)
1872 { # special case: search for "find" utility
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001873 if(`find \"$TMP_DIR\" -maxdepth 0 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001874 return "find";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001875 }
1876 }
1877 elsif($Name=~/gcc/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001878 return check_gcc($Name, "3");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001879 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001880 if(checkCmd($Name)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001881 return $Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001882 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001883 if($OSgroup eq "windows")
1884 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04001885 if(`$Name /? 2>\"$TMP_DIR/null\"`) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001886 return $Name;
1887 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001888 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001889 foreach my $Path (@DefaultBinPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001890 {
1891 if(-f $Path."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04001892 return join_P($Path, $Name);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001893 }
1894 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04001895 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001896}
1897
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001898sub classifyPath($)
1899{
1900 my $Path = $_[0];
1901 if($Path=~/[\*\[]/)
1902 { # wildcard
1903 $Path=~s/\*/.*/g;
1904 $Path=~s/\\/\\\\/g;
1905 return ($Path, "Pattern");
1906 }
1907 elsif($Path=~/[\/\\]/)
1908 { # directory or relative path
1909 return (path_format($Path, $OSgroup), "Path");
1910 }
1911 else {
1912 return ($Path, "Name");
1913 }
1914}
1915
1916sub readDescriptor($$)
1917{
1918 my ($LibVersion, $Content) = @_;
1919 return if(not $LibVersion);
1920 my $DName = $DumpAPI?"descriptor":"descriptor \"d$LibVersion\"";
1921 if(not $Content) {
1922 exitStatus("Error", "$DName is empty");
1923 }
1924 if($Content!~/\</) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04001925 exitStatus("Error", "incorrect descriptor (see -d1 option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001926 }
1927 $Content=~s/\/\*(.|\n)+?\*\///g;
1928 $Content=~s/<\!--(.|\n)+?-->//g;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04001929
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001930 $Descriptor{$LibVersion}{"Version"} = parseTag(\$Content, "version");
1931 if($TargetVersion{$LibVersion}) {
1932 $Descriptor{$LibVersion}{"Version"} = $TargetVersion{$LibVersion};
1933 }
1934 if(not $Descriptor{$LibVersion}{"Version"}) {
1935 exitStatus("Error", "version in the $DName is not specified (<version> section)");
1936 }
1937 if($Content=~/{RELPATH}/)
1938 {
1939 if(my $RelDir = $RelativeDirectory{$LibVersion}) {
1940 $Content =~ s/{RELPATH}/$RelDir/g;
1941 }
1942 else
1943 {
1944 my $NeedRelpath = $DumpAPI?"-relpath":"-relpath$LibVersion";
1945 exitStatus("Error", "you have not specified $NeedRelpath option, but the $DName contains {RELPATH} macro");
1946 }
1947 }
1948
1949 if(not $CheckObjectsOnly_Opt)
1950 {
1951 my $DHeaders = parseTag(\$Content, "headers");
1952 if(not $DHeaders) {
1953 exitStatus("Error", "header files in the $DName are not specified (<headers> section)");
1954 }
1955 elsif(lc($DHeaders) ne "none")
1956 { # append the descriptor headers list
1957 if($Descriptor{$LibVersion}{"Headers"})
1958 { # multiple descriptors
1959 $Descriptor{$LibVersion}{"Headers"} .= "\n".$DHeaders;
1960 }
1961 else {
1962 $Descriptor{$LibVersion}{"Headers"} = $DHeaders;
1963 }
1964 foreach my $Path (split(/\s*\n\s*/, $DHeaders))
1965 {
1966 if(not -e $Path) {
1967 exitStatus("Access_Error", "can't access \'$Path\'");
1968 }
1969 }
1970 }
1971 }
1972 if(not $CheckHeadersOnly_Opt)
1973 {
1974 my $DObjects = parseTag(\$Content, "libs");
1975 if(not $DObjects) {
1976 exitStatus("Error", "$SLIB_TYPE libraries in the $DName are not specified (<libs> section)");
1977 }
1978 elsif(lc($DObjects) ne "none")
1979 { # append the descriptor libraries list
1980 if($Descriptor{$LibVersion}{"Libs"})
1981 { # multiple descriptors
1982 $Descriptor{$LibVersion}{"Libs"} .= "\n".$DObjects;
1983 }
1984 else {
1985 $Descriptor{$LibVersion}{"Libs"} .= $DObjects;
1986 }
1987 foreach my $Path (split(/\s*\n\s*/, $DObjects))
1988 {
1989 if(not -e $Path) {
1990 exitStatus("Access_Error", "can't access \'$Path\'");
1991 }
1992 }
1993 }
1994 }
1995 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_headers")))
1996 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04001997 if(not -d $Path) {
1998 exitStatus("Access_Error", "can't access directory \'$Path\'");
1999 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002000 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002001 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002002 push_U($SystemPaths{"include"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002003 }
2004 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "search_libs")))
2005 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002006 if(not -d $Path) {
2007 exitStatus("Access_Error", "can't access directory \'$Path\'");
2008 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002009 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002010 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002011 push_U($SystemPaths{"lib"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002012 }
2013 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "tools")))
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_U($SystemPaths{"bin"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002021 $TargetTools{$Path}=1;
2022 }
2023 if(my $Prefix = parseTag(\$Content, "cross_prefix")) {
2024 $CrossPrefix = $Prefix;
2025 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002026 $Descriptor{$LibVersion}{"IncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"IncludePaths"}); # perl 5.8 doesn't support //=
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002027 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "include_paths")))
2028 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002029 if(not -d $Path) {
2030 exitStatus("Access_Error", "can't access directory \'$Path\'");
2031 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002032 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002033 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002034 push(@{$Descriptor{$LibVersion}{"IncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002035 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002036 $Descriptor{$LibVersion}{"AddIncludePaths"} = [] if(not defined $Descriptor{$LibVersion}{"AddIncludePaths"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002037 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "add_include_paths")))
2038 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002039 if(not -d $Path) {
2040 exitStatus("Access_Error", "can't access directory \'$Path\'");
2041 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002042 $Path = get_abs_path($Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002043 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002044 push(@{$Descriptor{$LibVersion}{"AddIncludePaths"}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002045 }
2046 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_include_paths")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002047 { # skip some auto-generated include paths
2048 if(not is_abs($Path))
2049 {
2050 if(my $P = abs_path($Path)) {
2051 $Path = $P;
2052 }
2053 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002054 $Skip_Include_Paths{$LibVersion}{path_format($Path)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002055 }
2056 foreach my $Path (split(/\s*\n\s*/, parseTag(\$Content, "skip_including")))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002057 { # skip direct including of some headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002058 my ($CPath, $Type) = classifyPath($Path);
2059 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002060 }
2061 $Descriptor{$LibVersion}{"GccOptions"} = parseTag(\$Content, "gcc_options");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002062 foreach my $Option (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"GccOptions"}))
2063 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04002064 if($Option!~/\A\-(Wl|l|L)/)
2065 { # skip linker options
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002066 $CompilerOptions{$LibVersion} .= " ".$Option;
2067 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002068 }
2069 $Descriptor{$LibVersion}{"SkipHeaders"} = parseTag(\$Content, "skip_headers");
2070 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipHeaders"}))
2071 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002072 $SkipHeadersList{$LibVersion}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002073 my ($CPath, $Type) = classifyPath($Path);
2074 $SkipHeaders{$LibVersion}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002075 }
2076 $Descriptor{$LibVersion}{"SkipLibs"} = parseTag(\$Content, "skip_libs");
2077 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"SkipLibs"}))
2078 {
2079 my ($CPath, $Type) = classifyPath($Path);
2080 $SkipLibs{$LibVersion}{$Type}{$CPath} = 1;
2081 }
2082 if(my $DDefines = parseTag(\$Content, "defines"))
2083 {
2084 if($Descriptor{$LibVersion}{"Defines"})
2085 { # multiple descriptors
2086 $Descriptor{$LibVersion}{"Defines"} .= "\n".$DDefines;
2087 }
2088 else {
2089 $Descriptor{$LibVersion}{"Defines"} = $DDefines;
2090 }
2091 }
2092 foreach my $Order (split(/\s*\n\s*/, parseTag(\$Content, "include_order")))
2093 {
2094 if($Order=~/\A(.+):(.+)\Z/) {
2095 $Include_Order{$LibVersion}{$1} = $2;
2096 }
2097 }
2098 foreach my $Type_Name (split(/\s*\n\s*/, parseTag(\$Content, "opaque_types")),
2099 split(/\s*\n\s*/, parseTag(\$Content, "skip_types")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002100 { # opaque_types renamed to skip_types (1.23.4)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002101 $SkipTypes{$LibVersion}{$Type_Name} = 1;
2102 }
2103 foreach my $Symbol (split(/\s*\n\s*/, parseTag(\$Content, "skip_interfaces")),
2104 split(/\s*\n\s*/, parseTag(\$Content, "skip_symbols")))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002105 { # skip_interfaces renamed to skip_symbols (1.22.1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002106 $SkipSymbols{$LibVersion}{$Symbol} = 1;
2107 }
2108 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "skip_namespaces"))) {
2109 $SkipNameSpaces{$LibVersion}{$NameSpace} = 1;
2110 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04002111 foreach my $NameSpace (split(/\s*\n\s*/, parseTag(\$Content, "add_namespaces"))) {
2112 $AddNameSpaces{$LibVersion}{$NameSpace} = 1;
2113 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002114 foreach my $Constant (split(/\s*\n\s*/, parseTag(\$Content, "skip_constants"))) {
2115 $SkipConstants{$LibVersion}{$Constant} = 1;
2116 }
2117 if(my $DIncPreamble = parseTag(\$Content, "include_preamble"))
2118 {
2119 if($Descriptor{$LibVersion}{"IncludePreamble"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04002120 { # multiple descriptors
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002121 $Descriptor{$LibVersion}{"IncludePreamble"} .= "\n".$DIncPreamble;
2122 }
2123 else {
2124 $Descriptor{$LibVersion}{"IncludePreamble"} = $DIncPreamble;
2125 }
2126 }
2127}
2128
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002129sub parseTag(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002130{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002131 my $CodeRef = shift(@_);
2132 my $Tag = shift(@_);
2133 if(not $Tag or not $CodeRef) {
2134 return undef;
2135 }
2136 my $Sp = 0;
2137 if(@_) {
2138 $Sp = shift(@_);
2139 }
2140 my $Start = index(${$CodeRef}, "<$Tag>");
2141 if($Start!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002142 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002143 my $End = index(${$CodeRef}, "</$Tag>");
2144 if($End!=-1)
2145 {
2146 my $TS = length($Tag)+3;
2147 my $Content = substr(${$CodeRef}, $Start, $End-$Start+$TS, "");
2148 substr($Content, 0, $TS-1, ""); # cut start tag
2149 substr($Content, -$TS, $TS, ""); # cut end tag
2150 if(not $Sp)
2151 {
2152 $Content=~s/\A\s+//g;
2153 $Content=~s/\s+\Z//g;
2154 }
2155 if(substr($Content, 0, 1) ne "<") {
2156 $Content = xmlSpecChars_R($Content);
2157 }
2158 return $Content;
2159 }
2160 }
2161 return undef;
2162}
2163
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002164sub getInfo($)
2165{
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002166 my $DumpPath = $_[0];
2167 return if(not $DumpPath or not -f $DumpPath);
2168
2169 readTUDump($DumpPath);
2170
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002171 # processing info
2172 setTemplateParams_All();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002173
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002174 if($ExtraDump) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002175 setAnonTypedef_All();
2176 }
2177
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002178 getTypeInfo_All();
2179 simplifyNames();
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002180 simplifyConstants();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002181 getVarInfo_All();
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002182 getSymbolInfo_All();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002183
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002184 # clean memory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002185 %LibInfo = ();
2186 %TemplateInstance = ();
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002187 %BasicTemplate = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002188 %MangledNames = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002189 %TemplateDecl = ();
2190 %StdCxxTypedef = ();
2191 %MissedTypedef = ();
2192 %Typedef_Tr = ();
2193 %Typedef_Eq = ();
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002194 %TypedefToAnon = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002195
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002196 # clean cache
2197 delete($Cache{"getTypeAttr"});
2198 delete($Cache{"getTypeDeclId"});
2199
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002200 if($ExtraDump)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002201 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002202 remove_Unused($Version, "Extra");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04002203 }
2204 else
2205 { # remove unused types
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002206 if($BinaryOnly and not $ExtendedCheck)
2207 { # --binary
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002208 remove_Unused($Version, "All");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002209 }
2210 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002211 remove_Unused($Version, "Extended");
2212 }
2213 }
2214
2215 if($CheckInfo)
2216 {
2217 foreach my $Tid (keys(%{$TypeInfo{$Version}})) {
2218 check_Completeness($TypeInfo{$Version}{$Tid}, $Version);
2219 }
2220
2221 foreach my $Sid (keys(%{$SymbolInfo{$Version}})) {
2222 check_Completeness($SymbolInfo{$Version}{$Sid}, $Version);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04002223 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002224 }
2225
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002226 if($Debug) {
2227 # debugMangling($Version);
2228 }
2229}
2230
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002231sub readTUDump($)
2232{
2233 my $DumpPath = $_[0];
2234
2235 open(TU_DUMP, $DumpPath);
2236 local $/ = undef;
2237 my $Content = <TU_DUMP>;
2238 close(TU_DUMP);
2239
2240 unlink($DumpPath);
2241
2242 $Content=~s/\n[ ]+/ /g;
2243 my @Lines = split("\n", $Content);
2244
2245 # clean memory
2246 undef $Content;
2247
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002248 $MAX_ID = $#Lines+1; # number of lines == number of nodes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002249
2250 foreach (0 .. $#Lines)
2251 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002252 if($Lines[$_]=~/\A\@(\d+)[ ]+([a-z_]+)[ ]+(.+)\Z/i)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002253 { # get a number and attributes of a node
2254 next if(not $NodeType{$2});
2255 $LibInfo{$Version}{"info_type"}{$1}=$2;
2256 $LibInfo{$Version}{"info"}{$1}=$3;
2257 }
2258
2259 # clean memory
2260 delete($Lines[$_]);
2261 }
2262
2263 # clean memory
2264 undef @Lines;
2265}
2266
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002267sub simplifyConstants()
2268{
2269 foreach my $Constant (keys(%{$Constants{$Version}}))
2270 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002271 if(defined $Constants{$Version}{$Constant}{"Header"})
2272 {
2273 my $Value = $Constants{$Version}{$Constant}{"Value"};
2274 if(defined $EnumConstants{$Version}{$Value}) {
2275 $Constants{$Version}{$Constant}{"Value"} = $EnumConstants{$Version}{$Value}{"Value"};
2276 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04002277 }
2278 }
2279}
2280
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002281sub simplifyNames()
2282{
2283 foreach my $Base (keys(%{$Typedef_Tr{$Version}}))
2284 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002285 if($Typedef_Eq{$Version}{$Base}) {
2286 next;
2287 }
2288 my @Translations = sort keys(%{$Typedef_Tr{$Version}{$Base}});
2289 if($#Translations==0)
2290 {
2291 if(length($Translations[0])<=length($Base)) {
2292 $Typedef_Eq{$Version}{$Base} = $Translations[0];
2293 }
2294 }
2295 else
2296 { # select most appropriate
2297 foreach my $Tr (@Translations)
2298 {
2299 if($Base=~/\A\Q$Tr\E/)
2300 {
2301 $Typedef_Eq{$Version}{$Base} = $Tr;
2302 last;
2303 }
2304 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002305 }
2306 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002307 foreach my $TypeId (keys(%{$TypeInfo{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002308 {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002309 my $TypeName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002310 if(not $TypeName) {
2311 next;
2312 }
2313 next if(index($TypeName,"<")==-1);# template instances only
2314 if($TypeName=~/>(::\w+)+\Z/)
2315 { # skip unused types
2316 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002317 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002318 foreach my $Base (sort {length($b)<=>length($a)}
2319 sort {$b cmp $a} keys(%{$Typedef_Eq{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002320 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002321 next if(not $Base);
2322 next if(index($TypeName,$Base)==-1);
2323 next if(length($TypeName) - length($Base) <= 3);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002324 if(my $Typedef = $Typedef_Eq{$Version}{$Base})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002325 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002326 $TypeName=~s/(\<|\,)\Q$Base\E(\W|\Z)/$1$Typedef$2/g;
2327 $TypeName=~s/(\<|\,)\Q$Base\E(\w|\Z)/$1$Typedef $2/g;
2328 if(defined $TypeInfo{$Version}{$TypeId}{"TParam"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002329 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002330 foreach my $TPos (keys(%{$TypeInfo{$Version}{$TypeId}{"TParam"}}))
2331 {
2332 if(my $TPName = $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"})
2333 {
2334 $TPName=~s/\A\Q$Base\E(\W|\Z)/$Typedef$1/g;
2335 $TPName=~s/\A\Q$Base\E(\w|\Z)/$Typedef $1/g;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002336 $TypeInfo{$Version}{$TypeId}{"TParam"}{$TPos}{"name"} = formatName($TPName, "T");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002337 }
2338 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002339 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002340 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002341 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002342 $TypeName = formatName($TypeName, "T");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002343 $TypeInfo{$Version}{$TypeId}{"Name"} = $TypeName;
2344 $TName_Tid{$Version}{$TypeName} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002345 }
2346}
2347
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04002348sub setAnonTypedef_All()
2349{
2350 foreach my $InfoId (keys(%{$LibInfo{$Version}{"info"}}))
2351 {
2352 if($LibInfo{$Version}{"info_type"}{$InfoId} eq "type_decl")
2353 {
2354 if(isAnon(getNameByInfo($InfoId))) {
2355 $TypedefToAnon{getTypeId($InfoId)} = 1;
2356 }
2357 }
2358 }
2359}
2360
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002361sub setTemplateParams_All()
2362{
2363 foreach (keys(%{$LibInfo{$Version}{"info"}}))
2364 {
2365 if($LibInfo{$Version}{"info_type"}{$_} eq "template_decl") {
2366 setTemplateParams($_);
2367 }
2368 }
2369}
2370
2371sub setTemplateParams($)
2372{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002373 my $Tid = getTypeId($_[0]);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002374 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002375 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002376 if($Info=~/(inst|spcs)[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002377 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002378 my $TmplInst_Id = $2;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002379 setTemplateInstParams($_[0], $TmplInst_Id);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002380 while($TmplInst_Id = getNextElem($TmplInst_Id)) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002381 setTemplateInstParams($_[0], $TmplInst_Id);
2382 }
2383 }
2384
2385 $BasicTemplate{$Version}{$Tid} = $_[0];
2386
2387 if(my $Prms = getTreeAttr_Prms($_[0]))
2388 {
2389 if(my $Valu = getTreeAttr_Valu($Prms))
2390 {
2391 my $Vector = getTreeVec($Valu);
2392 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Vector}))
2393 {
2394 if(my $Val = getTreeAttr_Valu($Vector->{$Pos}))
2395 {
2396 if(my $Name = getNameByInfo($Val))
2397 {
2398 $TemplateArg{$Version}{$_[0]}{$Pos} = $Name;
2399 if($LibInfo{$Version}{"info_type"}{$Val} eq "parm_decl") {
2400 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = $Val;
2401 }
2402 else {
2403 $TemplateInstance{$Version}{"Type"}{$Tid}{$Pos} = getTreeAttr_Type($Val);
2404 }
2405 }
2406 }
2407 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002408 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002409 }
2410 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002411 if(my $TypeId = getTreeAttr_Type($_[0]))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002412 {
2413 if(my $IType = $LibInfo{$Version}{"info_type"}{$TypeId})
2414 {
2415 if($IType eq "record_type") {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002416 $TemplateDecl{$Version}{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002417 }
2418 }
2419 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002420}
2421
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002422sub setTemplateInstParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002423{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002424 my ($Tmpl, $Inst) = @_;
2425
2426 if(my $Info = $LibInfo{$Version}{"info"}{$Inst})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002427 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002428 my ($Params_InfoId, $ElemId) = ();
2429 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
2430 $Params_InfoId = $1;
2431 }
2432 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
2433 $ElemId = $1;
2434 }
2435 if($Params_InfoId and $ElemId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002436 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002437 my $Params_Info = $LibInfo{$Version}{"info"}{$Params_InfoId};
2438 while($Params_Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
2439 {
2440 my ($PPos, $PTypeId) = ($1, $2);
2441 if(my $PType = $LibInfo{$Version}{"info_type"}{$PTypeId})
2442 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002443 if($PType eq "template_type_parm") {
2444 $TemplateDecl{$Version}{$ElemId} = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002445 }
2446 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002447 if($LibInfo{$Version}{"info_type"}{$ElemId} eq "function_decl")
2448 { # functions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002449 $TemplateInstance{$Version}{"Func"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002450 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002451 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04002452 else
2453 { # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002454 $TemplateInstance{$Version}{"Type"}{$ElemId}{$PPos} = $PTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002455 $BasicTemplate{$Version}{$ElemId} = $Tmpl;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002456 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002457 }
2458 }
2459 }
2460}
2461
2462sub getTypeDeclId($)
2463{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002464 if($_[0])
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002465 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002466 if(defined $Cache{"getTypeDeclId"}{$Version}{$_[0]}) {
2467 return $Cache{"getTypeDeclId"}{$Version}{$_[0]};
2468 }
2469 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
2470 {
2471 if($Info=~/name[ ]*:[ ]*@(\d+)/) {
2472 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = $1);
2473 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04002474 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002475 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002476 return ($Cache{"getTypeDeclId"}{$Version}{$_[0]} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002477}
2478
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002479sub getTypeInfo_All()
2480{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002481 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002482 { # support for GCC < 4.5
2483 # missed typedefs: QStyle::State is typedef to QFlags<QStyle::StateFlag>
2484 # but QStyleOption.state is of type QFlags<QStyle::StateFlag> in the TU dump
2485 # FIXME: check GCC versions
2486 addMissedTypes_Pre();
2487 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002488
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002489 foreach (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002490 { # forward order only
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002491 my $IType = $LibInfo{$Version}{"info_type"}{$_};
2492 if($IType=~/_type\Z/ and $IType ne "function_type"
2493 and $IType ne "method_type") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002494 getTypeInfo("$_");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002495 }
2496 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002497
2498 # add "..." type
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002499 $TypeInfo{$Version}{"-1"} = {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002500 "Name" => "...",
2501 "Type" => "Intrinsic",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002502 "Tid" => "-1"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002503 };
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04002504 $TName_Tid{$Version}{"..."} = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002505
2506 if(not check_gcc($GCC_PATH, "4.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002507 { # support for GCC < 4.5
2508 addMissedTypes_Post();
2509 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002510
2511 if($ADD_TMPL_INSTANCES)
2512 {
2513 # templates
2514 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}}))
2515 {
2516 if(defined $TemplateMap{$Version}{$Tid}
2517 and not defined $TypeInfo{$Version}{$Tid}{"Template"})
2518 {
2519 if(defined $TypeInfo{$Version}{$Tid}{"Memb"})
2520 {
2521 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Memb"}}))
2522 {
2523 if(my $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"})
2524 {
2525 if(my %MAttr = getTypeAttr($MembTypeId))
2526 {
2527 $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"algn"} = $MAttr{"Algn"};
2528 $MembTypeId = $TypeInfo{$Version}{$Tid}{"Memb"}{$Pos}{"type"} = instType($TemplateMap{$Version}{$Tid}, $MembTypeId, $Version);
2529 }
2530 }
2531 }
2532 }
2533 if(defined $TypeInfo{$Version}{$Tid}{"Base"})
2534 {
2535 foreach my $Bid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$Version}{$Tid}{"Base"}}))
2536 {
2537 my $NBid = instType($TemplateMap{$Version}{$Tid}, $Bid, $Version);
2538
2539 if($NBid ne $Bid)
2540 {
2541 %{$TypeInfo{$Version}{$Tid}{"Base"}{$NBid}} = %{$TypeInfo{$Version}{$Tid}{"Base"}{$Bid}};
2542 delete($TypeInfo{$Version}{$Tid}{"Base"}{$Bid});
2543 }
2544 }
2545 }
2546 }
2547 }
2548 }
2549}
2550
2551sub createType($$)
2552{
2553 my ($Attr, $LibVersion) = @_;
2554 my $NewId = ++$MAX_ID;
2555
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04002556 $Attr->{"Tid"} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002557 $TypeInfo{$Version}{$NewId} = $Attr;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002558 $TName_Tid{$Version}{formatName($Attr->{"Name"}, "T")} = $NewId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002559
2560 return "$NewId";
2561}
2562
2563sub instType($$$)
2564{ # create template instances
2565 my ($Map, $Tid, $LibVersion) = @_;
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002566
2567 if(not $TypeInfo{$LibVersion}{$Tid}) {
2568 return undef;
2569 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002570 my $Attr = dclone($TypeInfo{$LibVersion}{$Tid});
2571
2572 foreach my $Key (sort keys(%{$Map}))
2573 {
2574 if(my $Val = $Map->{$Key})
2575 {
2576 $Attr->{"Name"}=~s/\b$Key\b/$Val/g;
2577
2578 if(defined $Attr->{"NameSpace"}) {
2579 $Attr->{"NameSpace"}=~s/\b$Key\b/$Val/g;
2580 }
2581 foreach (keys(%{$Attr->{"TParam"}})) {
2582 $Attr->{"TParam"}{$_}{"name"}=~s/\b$Key\b/$Val/g;
2583 }
2584 }
2585 else
2586 { # remove absent
2587 # _Traits, etc.
2588 $Attr->{"Name"}=~s/,\s*\b$Key(,|>)/$1/g;
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002589 if(defined $Attr->{"NameSpace"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002590 $Attr->{"NameSpace"}=~s/,\s*\b$Key(,|>)/$1/g;
2591 }
2592 foreach (keys(%{$Attr->{"TParam"}}))
2593 {
2594 if($Attr->{"TParam"}{$_}{"name"} eq $Key) {
2595 delete($Attr->{"TParam"}{$_});
2596 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002597 else {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002598 $Attr->{"TParam"}{$_}{"name"}=~s/,\s*\b$Key(,|>)/$1/g;
2599 }
2600 }
2601 }
2602 }
2603
2604 my $Tmpl = 0;
2605
2606 if(defined $Attr->{"TParam"})
2607 {
2608 foreach (sort {int($a)<=>int($b)} keys(%{$Attr->{"TParam"}}))
2609 {
2610 my $PName = $Attr->{"TParam"}{$_}{"name"};
2611
2612 if(my $PTid = $TName_Tid{$LibVersion}{$PName})
2613 {
2614 my %Base = get_BaseType($PTid, $LibVersion);
2615
2616 if($Base{"Type"} eq "TemplateParam"
2617 or defined $Base{"Template"})
2618 {
2619 $Tmpl = 1;
2620 last
2621 }
2622 }
2623 }
2624 }
2625
2626 if(my $Id = getTypeIdByName($Attr->{"Name"}, $LibVersion)) {
2627 return "$Id";
2628 }
2629 else
2630 {
2631 if(not $Tmpl) {
2632 delete($Attr->{"Template"});
2633 }
2634
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002635 my $New = createType($Attr, $LibVersion);
2636
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002637 my %EMap = ();
2638 if(defined $TemplateMap{$LibVersion}{$Tid}) {
2639 %EMap = %{$TemplateMap{$LibVersion}{$Tid}};
2640 }
2641 foreach (keys(%{$Map})) {
2642 $EMap{$_} = $Map->{$_};
2643 }
2644
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002645 if(defined $TypeInfo{$LibVersion}{$New}{"BaseType"}) {
2646 $TypeInfo{$LibVersion}{$New}{"BaseType"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"BaseType"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002647 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002648 if(defined $TypeInfo{$LibVersion}{$New}{"Base"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002649 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002650 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$New}{"Base"}}))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002651 {
2652 my $NBid = instType(\%EMap, $Bid, $LibVersion);
2653
2654 if($NBid ne $Bid)
2655 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002656 %{$TypeInfo{$LibVersion}{$New}{"Base"}{$NBid}} = %{$TypeInfo{$LibVersion}{$New}{"Base"}{$Bid}};
2657 delete($TypeInfo{$LibVersion}{$New}{"Base"}{$Bid});
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002658 }
2659 }
2660 }
2661
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002662 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002663 {
Andrey Ponomarenkobe558b82013-07-01 11:28:09 +04002664 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Memb"}}))
2665 {
2666 if(defined $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}) {
2667 $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Memb"}{$_}{"type"}, $LibVersion);
2668 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002669 }
2670 }
2671
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002672 if(defined $TypeInfo{$LibVersion}{$New}{"Param"})
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002673 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002674 foreach (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}{$New}{"Param"}})) {
2675 $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Param"}{$_}{"type"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002676 }
2677 }
2678
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002679 if(defined $TypeInfo{$LibVersion}{$New}{"Return"}) {
2680 $TypeInfo{$LibVersion}{$New}{"Return"} = instType(\%EMap, $TypeInfo{$LibVersion}{$New}{"Return"}, $LibVersion);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002681 }
2682
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04002683 return $New;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002684 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002685}
2686
2687sub addMissedTypes_Pre()
2688{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002689 my %MissedTypes = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002690 foreach my $MissedTDid (sort {int($a)<=>int($b)} keys(%{$LibInfo{$Version}{"info"}}))
2691 { # detecting missed typedefs
2692 if($LibInfo{$Version}{"info_type"}{$MissedTDid} eq "type_decl")
2693 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002694 my $TypeId = getTreeAttr_Type($MissedTDid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002695 next if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002696 my $TypeType = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002697 if($TypeType eq "Unknown")
2698 { # template_type_parm
2699 next;
2700 }
2701 my $TypeDeclId = getTypeDeclId($TypeId);
2702 next if($TypeDeclId eq $MissedTDid);#or not $TypeDeclId
2703 my $TypedefName = getNameByInfo($MissedTDid);
2704 next if(not $TypedefName);
2705 next if($TypedefName eq "__float80");
2706 next if(isAnon($TypedefName));
2707 if(not $TypeDeclId
2708 or getNameByInfo($TypeDeclId) ne $TypedefName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002709 $MissedTypes{$Version}{$TypeId}{$MissedTDid} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002710 }
2711 }
2712 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002713 my %AddTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002714 foreach my $Tid (keys(%{$MissedTypes{$Version}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002715 { # add missed typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002716 my @Missed = keys(%{$MissedTypes{$Version}{$Tid}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002717 if(not @Missed or $#Missed>=1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002718 next;
2719 }
2720 my $MissedTDid = $Missed[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002721 my ($TypedefName, $TypedefNS) = getTrivialName($MissedTDid, $Tid);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002722 if(not $TypedefName) {
2723 next;
2724 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002725 my $NewId = ++$MAX_ID;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002726 my %MissedInfo = ( # typedef info
2727 "Name" => $TypedefName,
2728 "NameSpace" => $TypedefNS,
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002729 "BaseType" => $Tid,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002730 "Type" => "Typedef",
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002731 "Tid" => "$NewId" );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002732 my ($H, $L) = getLocation($MissedTDid);
2733 $MissedInfo{"Header"} = $H;
2734 $MissedInfo{"Line"} = $L;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002735 if($TypedefName=~/\*|\&|\s/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002736 { # other types
2737 next;
2738 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002739 if($TypedefName=~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002740 { # QFlags<Qt::DropAction>::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002741 next;
2742 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002743 if(getTypeType($Tid)=~/\A(Intrinsic|Union|Struct|Enum|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002744 { # double-check for the name of typedef
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002745 my ($TName, $TNS) = getTrivialName(getTypeDeclId($Tid), $Tid); # base type info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002746 next if(not $TName);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002747 if(length($TypedefName)>=length($TName))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002748 { # too long typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002749 next;
2750 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002751 if($TName=~/\A\Q$TypedefName\E</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002752 next;
2753 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002754 if($TypedefName=~/\A\Q$TName\E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002755 { # QDateTimeEdit::Section and QDateTimeEdit::Sections::enum_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002756 next;
2757 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002758 if(get_depth($TypedefName)==0 and get_depth($TName)!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002759 { # std::_Vector_base and std::vector::_Base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002760 next;
2761 }
2762 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002763
2764 $AddTypes{$MissedInfo{"Tid"}} = \%MissedInfo;
2765
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002766 # register typedef
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002767 $MissedTypedef{$Version}{$Tid}{"Tid"} = $MissedInfo{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002768 $MissedTypedef{$Version}{$Tid}{"TDid"} = $MissedTDid;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002769 $TName_Tid{$Version}{$TypedefName} = $MissedInfo{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002770 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002771
2772 # add missed & remove other
2773 $TypeInfo{$Version} = \%AddTypes;
2774 delete($Cache{"getTypeAttr"}{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002775}
2776
2777sub addMissedTypes_Post()
2778{
2779 foreach my $BaseId (keys(%{$MissedTypedef{$Version}}))
2780 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002781 if(my $Tid = $MissedTypedef{$Version}{$BaseId}{"Tid"})
2782 {
2783 $TypeInfo{$Version}{$Tid}{"Size"} = $TypeInfo{$Version}{$BaseId}{"Size"};
2784 if(my $TName = $TypeInfo{$Version}{$Tid}{"Name"}) {
2785 $Typedef_BaseName{$Version}{$TName} = $TypeInfo{$Version}{$BaseId}{"Name"};
2786 }
2787 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002788 }
2789}
2790
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002791sub getTypeInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002792{
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002793 my $TypeId = $_[0];
2794 %{$TypeInfo{$Version}{$TypeId}} = getTypeAttr($TypeId);
2795 my $TName = $TypeInfo{$Version}{$TypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002796 if(not $TName) {
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04002797 delete($TypeInfo{$Version}{$TypeId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002798 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002799}
2800
2801sub getArraySize($$)
2802{
2803 my ($TypeId, $BaseName) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002804 if(my $Size = getSize($TypeId))
2805 {
2806 my $Elems = $Size/$BYTE_SIZE;
2807 while($BaseName=~s/\s*\[(\d+)\]//) {
2808 $Elems/=$1;
2809 }
2810 if(my $BasicId = $TName_Tid{$Version}{$BaseName})
2811 {
2812 if(my $BasicSize = $TypeInfo{$Version}{$BasicId}{"Size"}) {
2813 $Elems/=$BasicSize;
2814 }
2815 }
2816 return $Elems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002817 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002818 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002819}
2820
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002821sub getTParams($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002822{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002823 my ($TypeId, $Kind) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002824 my @TmplParams = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002825 my @Positions = sort {int($a)<=>int($b)} keys(%{$TemplateInstance{$Version}{$Kind}{$TypeId}});
2826 foreach my $Pos (@Positions)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002827 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002828 my $Param_TypeId = $TemplateInstance{$Version}{$Kind}{$TypeId}{$Pos};
2829 my $NodeType = $LibInfo{$Version}{"info_type"}{$Param_TypeId};
2830 if(not $NodeType)
2831 { # typename_type
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002832 return ();
2833 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002834 if($NodeType eq "tree_vec")
2835 {
2836 if($Pos!=$#Positions)
2837 { # select last vector of parameters ( ns<P1>::type<P2> )
2838 next;
2839 }
2840 }
2841 my @Params = get_TemplateParam($Pos, $Param_TypeId);
2842 foreach my $P (@Params)
2843 {
2844 if($P eq "") {
2845 return ();
2846 }
2847 elsif($P ne "\@skip\@") {
2848 @TmplParams = (@TmplParams, $P);
2849 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002850 }
2851 }
2852 return @TmplParams;
2853}
2854
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002855sub getTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002856{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002857 my $TypeId = $_[0];
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002858 my %TypeAttr = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002859 if(defined $TypeInfo{$Version}{$TypeId}
2860 and $TypeInfo{$Version}{$TypeId}{"Name"})
2861 { # already created
2862 return %{$TypeInfo{$Version}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002863 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002864 elsif($Cache{"getTypeAttr"}{$Version}{$TypeId})
2865 { # incomplete type
2866 return ();
2867 }
2868 $Cache{"getTypeAttr"}{$Version}{$TypeId} = 1;
2869
2870 my $TypeDeclId = getTypeDeclId($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002871 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002872
2873 if(not $MissedBase{$Version}{$TypeId} and isTypedef($TypeId))
2874 {
2875 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
2876 {
2877 if($Info=~/qual[ ]*:/)
2878 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002879 my $NewId = ++$MAX_ID;
2880
2881 $MissedBase{$Version}{$TypeId} = "$NewId";
2882 $MissedBase_R{$Version}{$NewId} = $TypeId;
2883 $LibInfo{$Version}{"info"}{$NewId} = $LibInfo{$Version}{"info"}{$TypeId};
2884 $LibInfo{$Version}{"info_type"}{$NewId} = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002885 }
2886 }
2887 $TypeAttr{"Type"} = "Typedef";
2888 }
2889 else {
2890 $TypeAttr{"Type"} = getTypeType($TypeId);
2891 }
2892
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002893 if(my $ScopeId = getTreeAttr_Scpe($TypeDeclId))
2894 {
2895 if($LibInfo{$Version}{"info_type"}{$ScopeId} eq "function_decl")
2896 { # local code
2897 return ();
2898 }
2899 }
2900
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002901 if($TypeAttr{"Type"} eq "Unknown") {
2902 return ();
2903 }
2904 elsif($TypeAttr{"Type"}=~/(Func|Method|Field)Ptr/)
2905 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002906 %TypeAttr = getMemPtrAttr(pointTo($TypeId), $TypeId, $TypeAttr{"Type"});
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002907 if(my $TName = $TypeAttr{"Name"})
2908 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002909 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002910 $TName_Tid{$Version}{$TName} = $TypeId;
2911 return %TypeAttr;
2912 }
2913 else {
2914 return ();
2915 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002916 }
2917 elsif($TypeAttr{"Type"} eq "Array")
2918 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002919 my ($BTid, $BTSpec) = selectBaseType($TypeId);
2920 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002921 return ();
2922 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04002923 if(my $Algn = getAlgn($TypeId)) {
2924 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
2925 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04002926 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002927 if(my %BTAttr = getTypeAttr($BTid))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002928 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002929 if(not $BTAttr{"Name"}) {
2930 return ();
2931 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002932 if(my $NElems = getArraySize($TypeId, $BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002933 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002934 if(my $Size = getSize($TypeId)) {
2935 $TypeAttr{"Size"} = $Size/$BYTE_SIZE;
2936 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002937 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002938 $TypeAttr{"Name"} = $1."[$NElems]".$2;
2939 }
2940 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002941 $TypeAttr{"Name"} = $BTAttr{"Name"}."[$NElems]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002942 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002943 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002944 else
2945 {
2946 $TypeAttr{"Size"} = $WORD_SIZE{$Version}; # pointer
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002947 if($BTAttr{"Name"}=~/\A([^\[\]]+)(\[(\d+|)\].*)\Z/) {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002948 $TypeAttr{"Name"} = $1."[]".$2;
2949 }
2950 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002951 $TypeAttr{"Name"} = $BTAttr{"Name"}."[]";
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002952 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002953 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04002954 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002955 if($BTAttr{"Header"}) {
2956 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002957 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002958 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002959 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2960 return %TypeAttr;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002961 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002962 return ();
2963 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002964 elsif($TypeAttr{"Type"}=~/\A(Intrinsic|Union|Struct|Enum|Class|Vector)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002965 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002966 %TypeAttr = getTrivialTypeAttr($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002967 if($TypeAttr{"Name"})
2968 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04002969 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002970
2971 if(not defined $IntrinsicNames{$TypeAttr{"Name"}}
2972 or getTypeDeclId($TypeAttr{"Tid"}))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04002973 { # NOTE: register only one int: with built-in decl
2974 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2975 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2976 }
2977 }
2978 return %TypeAttr;
2979 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04002980 else {
2981 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002982 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04002983 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04002984 elsif($TypeAttr{"Type"}=~/TemplateParam|TypeName/)
2985 {
2986 %TypeAttr = getTrivialTypeAttr($TypeId);
2987 if($TypeAttr{"Name"})
2988 {
2989 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
2990 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
2991 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
2992 }
2993 return %TypeAttr;
2994 }
2995 else {
2996 return ();
2997 }
2998 }
2999 elsif($TypeAttr{"Type"} eq "SizeOf")
3000 {
3001 $TypeAttr{"BaseType"} = getTreeAttr_Type($TypeId);
3002 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
3003 $TypeAttr{"Name"} = "sizeof(".$BTAttr{"Name"}.")";
3004 if($TypeAttr{"Name"})
3005 {
3006 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
3007 return %TypeAttr;
3008 }
3009 else {
3010 return ();
3011 }
3012 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003013 else
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003014 { # derived types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003015 my ($BTid, $BTSpec) = selectBaseType($TypeId);
3016 if(not $BTid) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003017 return ();
3018 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003019 $TypeAttr{"BaseType"} = $BTid;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003020 if(defined $MissedTypedef{$Version}{$BTid})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003021 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003022 if(my $MissedTDid = $MissedTypedef{$Version}{$BTid}{"TDid"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003023 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003024 if($MissedTDid ne $TypeDeclId) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003025 $TypeAttr{"BaseType"} = $MissedTypedef{$Version}{$BTid}{"Tid"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003026 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003027 }
3028 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003029 my %BTAttr = getTypeAttr($TypeAttr{"BaseType"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003030 if(not $BTAttr{"Name"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003031 { # templates
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003032 return ();
3033 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003034 if($BTAttr{"Type"} eq "Typedef")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003035 { # relinking typedefs
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003036 my %BaseBase = get_Type($BTAttr{"BaseType"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003037 if($BTAttr{"Name"} eq $BaseBase{"Name"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04003038 $TypeAttr{"BaseType"} = $BaseBase{"Tid"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003039 }
3040 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003041 if($BTSpec)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003042 {
3043 if($TypeAttr{"Type"} eq "Pointer"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003044 and $BTAttr{"Name"}=~/\([\*]+\)/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003045 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003046 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003047 $TypeAttr{"Name"}=~s/\(([*]+)\)/($1*)/g;
3048 }
3049 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003050 $TypeAttr{"Name"} = $BTAttr{"Name"}." ".$BTSpec;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003051 }
3052 }
3053 else {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003054 $TypeAttr{"Name"} = $BTAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003055 }
3056 if($TypeAttr{"Type"} eq "Typedef")
3057 {
3058 $TypeAttr{"Name"} = getNameByInfo($TypeDeclId);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003059
3060 if(index($TypeAttr{"Name"}, "tmp_add_type")==0) {
3061 return ();
3062 }
3063
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003064 if(isAnon($TypeAttr{"Name"}))
3065 { # anon typedef to anon type: ._N
3066 return ();
3067 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003068
3069 if($LibInfo{$Version}{"info"}{$TypeDeclId}=~/ artificial /i)
3070 { # artificial typedef of "struct X" to "X"
3071 $TypeAttr{"Artificial"} = 1;
3072 }
3073
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003074 if(my $NS = getNameSpace($TypeDeclId))
3075 {
3076 my $TypeName = $TypeAttr{"Name"};
3077 if($NS=~/\A(struct |union |class |)((.+)::|)\Q$TypeName\E\Z/)
3078 { # "some_type" is the typedef to "struct some_type" in C++
3079 if($3) {
3080 $TypeAttr{"Name"} = $3."::".$TypeName;
3081 }
3082 }
3083 else
3084 {
3085 $TypeAttr{"NameSpace"} = $NS;
3086 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003087
3088 if($TypeAttr{"NameSpace"}=~/\Astd(::|\Z)/
3089 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/)
3090 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003091 if($BTAttr{"NameSpace"}
3092 and $BTAttr{"NameSpace"}=~/\Astd(::|\Z)/ and $BTAttr{"Name"}=~/</)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003093 { # types like "std::fpos<__mbstate_t>" are
3094 # not covered by typedefs in the TU dump
3095 # so trying to add such typedefs manually
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003096 $StdCxxTypedef{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3097 if(length($TypeAttr{"Name"})<=length($BTAttr{"Name"}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003098 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003099 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003100 { # skip "other" in "std" and "type" in "boost"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003101 $Typedef_Eq{$Version}{$BTAttr{"Name"}} = $TypeAttr{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003102 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003103 }
3104 }
3105 }
3106 }
3107 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04003108 if($TypeAttr{"Name"} ne $BTAttr{"Name"} and not $TypeAttr{"Artificial"}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003109 and $TypeAttr{"Name"}!~/>(::\w+)+\Z/ and $BTAttr{"Name"}!~/>(::\w+)+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003110 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003111 if(not defined $Typedef_BaseName{$Version}{$TypeAttr{"Name"}})
3112 { # typedef int*const TYPEDEF; // first
3113 # int foo(TYPEDEF p); // const is optimized out
3114 $Typedef_BaseName{$Version}{$TypeAttr{"Name"}} = $BTAttr{"Name"};
3115 if($BTAttr{"Name"}=~/</)
3116 {
3117 if(($BTAttr{"Name"}!~/\A(std|boost)::/ or $TypeAttr{"Name"}!~/\A[a-z]+\Z/)) {
3118 $Typedef_Tr{$Version}{$BTAttr{"Name"}}{$TypeAttr{"Name"}} = 1;
3119 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003120 }
3121 }
3122 }
3123 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeDeclId);
3124 }
3125 if(not $TypeAttr{"Size"})
3126 {
3127 if($TypeAttr{"Type"} eq "Pointer") {
3128 $TypeAttr{"Size"} = $WORD_SIZE{$Version};
3129 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003130 elsif($BTAttr{"Size"}) {
3131 $TypeAttr{"Size"} = $BTAttr{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003132 }
3133 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003134 if(my $Algn = getAlgn($TypeId)) {
3135 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3136 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003137 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003138 if(not $TypeAttr{"Header"} and $BTAttr{"Header"}) {
3139 $TypeAttr{"Header"} = $BTAttr{"Header"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003140 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003141 %{$TypeInfo{$Version}{$TypeId}} = %TypeAttr;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003142 if($TypeAttr{"Name"} ne $BTAttr{"Name"})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003143 { # typedef to "class Class"
3144 # should not be registered in TName_Tid
3145 if(not $TName_Tid{$Version}{$TypeAttr{"Name"}}) {
3146 $TName_Tid{$Version}{$TypeAttr{"Name"}} = $TypeId;
3147 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003148 }
3149 return %TypeAttr;
3150 }
3151}
3152
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003153sub getTreeVec($)
3154{
3155 my %Vector = ();
3156 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3157 {
3158 while($Info=~s/ (\d+)[ ]*:[ ]*\@(\d+) / /)
3159 { # string length is N-1 because of the null terminator
3160 $Vector{$1} = $2;
3161 }
3162 }
3163 return \%Vector;
3164}
3165
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003166sub get_TemplateParam($$)
3167{
3168 my ($Pos, $Type_Id) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003169 return () if(not $Type_Id);
3170 my $NodeType = $LibInfo{$Version}{"info_type"}{$Type_Id};
3171 return () if(not $NodeType);
3172 if($NodeType eq "integer_cst")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003173 { # int (1), unsigned (2u), char ('c' as 99), ...
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003174 my $CstTid = getTreeAttr_Type($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003175 my %CstType = getTypeAttr($CstTid); # without recursion
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003176 my $Num = getNodeIntCst($Type_Id);
3177 if(my $CstSuffix = $ConstantSuffix{$CstType{"Name"}}) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003178 return ($Num.$CstSuffix);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003179 }
3180 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003181 return ("(".$CstType{"Name"}.")".$Num);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003182 }
3183 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003184 elsif($NodeType eq "string_cst") {
3185 return (getNodeStrCst($Type_Id));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003186 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003187 elsif($NodeType eq "tree_vec")
3188 {
3189 my $Vector = getTreeVec($Type_Id);
3190 my @Params = ();
3191 foreach my $P1 (sort {int($a)<=>int($b)} keys(%{$Vector}))
3192 {
3193 foreach my $P2 (get_TemplateParam($Pos, $Vector->{$P1})) {
3194 push(@Params, $P2);
3195 }
3196 }
3197 return @Params;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003198 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003199 elsif($NodeType eq "parm_decl")
3200 {
3201 (getNameByInfo($Type_Id));
3202 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003203 else
3204 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003205 my %ParamAttr = getTypeAttr($Type_Id);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003206 my $PName = $ParamAttr{"Name"};
3207 if(not $PName) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003208 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003209 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003210 if($PName=~/\>/)
3211 {
3212 if(my $Cover = cover_stdcxx_typedef($PName)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003213 $PName = $Cover;
3214 }
3215 }
3216 if($Pos>=1 and
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04003217 $PName=~/\A$DEFAULT_STD_PARMS\</)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003218 { # template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
3219 # template<typename _Key, typename _Compare = std::less<_Key>
3220 # template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
3221 # template<typename _Ch_type, typename _Rx_traits = regex_traits<_Ch_type> >
3222 # template<typename _CharT, typename _InIter = istreambuf_iterator<_CharT> >
3223 # template<typename _CharT, typename _OutIter = ostreambuf_iterator<_CharT> >
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003224 return ("\@skip\@");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003225 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003226 return ($PName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003227 }
3228}
3229
3230sub cover_stdcxx_typedef($)
3231{
3232 my $TypeName = $_[0];
3233 if(my @Covers = sort {length($a)<=>length($b)}
3234 sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3235 { # take the shortest typedef
3236 # FIXME: there may be more than
3237 # one typedefs to the same type
3238 return $Covers[0];
3239 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003240 my $Covered = $TypeName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003241 while($TypeName=~s/(>)[ ]*(const|volatile|restrict| |\*|\&)\Z/$1/g){};
3242 if(my @Covers = sort {length($a)<=>length($b)} sort keys(%{$StdCxxTypedef{$Version}{$TypeName}}))
3243 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003244 if(my $Cover = $Covers[0])
3245 {
3246 $Covered=~s/\b\Q$TypeName\E(\W|\Z)/$Cover$1/g;
3247 $Covered=~s/\b\Q$TypeName\E(\w|\Z)/$Cover $1/g;
3248 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003249 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003250 return formatName($Covered, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003251}
3252
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003253sub getNodeIntCst($)
3254{
3255 my $CstId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003256 my $CstTypeId = getTreeAttr_Type($CstId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003257 if($EnumMembName_Id{$Version}{$CstId}) {
3258 return $EnumMembName_Id{$Version}{$CstId};
3259 }
3260 elsif((my $Value = getTreeValue($CstId)) ne "")
3261 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003262 if($Value eq "0")
3263 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003264 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003265 return "false";
3266 }
3267 else {
3268 return "0";
3269 }
3270 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003271 elsif($Value eq "1")
3272 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003273 if($LibInfo{$Version}{"info_type"}{$CstTypeId} eq "boolean_type") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003274 return "true";
3275 }
3276 else {
3277 return "1";
3278 }
3279 }
3280 else {
3281 return $Value;
3282 }
3283 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003284 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003285}
3286
3287sub getNodeStrCst($)
3288{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003289 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3290 {
3291 if($Info=~/strg[ ]*: (.+) lngt:[ ]*(\d+)/)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003292 {
3293 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "string_cst")
3294 { # string length is N-1 because of the null terminator
3295 return substr($1, 0, $2-1);
3296 }
3297 else
3298 { # identifier_node
3299 return substr($1, 0, $2);
3300 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003301 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003302 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003303 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003304}
3305
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003306sub getMemPtrAttr($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003307{ # function, method and field pointers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003308 my ($PtrId, $TypeId, $Type) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003309 my $MemInfo = $LibInfo{$Version}{"info"}{$PtrId};
3310 if($Type eq "FieldPtr") {
3311 $MemInfo = $LibInfo{$Version}{"info"}{$TypeId};
3312 }
3313 my $MemInfo_Type = $LibInfo{$Version}{"info_type"}{$PtrId};
3314 my $MemPtrName = "";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003315 my %TypeAttr = ("Size"=>$WORD_SIZE{$Version}, "Type"=>$Type, "Tid"=>$TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003316 if($Type eq "MethodPtr")
3317 { # size of "method pointer" may be greater than WORD size
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003318 if(my $Size = getSize($TypeId))
3319 {
3320 $Size/=$BYTE_SIZE;
3321 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003322 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003323 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003324 if(my $Algn = getAlgn($TypeId)) {
3325 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
3326 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003327 # Return
3328 if($Type eq "FieldPtr")
3329 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003330 my %ReturnAttr = getTypeAttr($PtrId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003331 if($ReturnAttr{"Name"}) {
3332 $MemPtrName .= $ReturnAttr{"Name"};
3333 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003334 $TypeAttr{"Return"} = $PtrId;
3335 }
3336 else
3337 {
3338 if($MemInfo=~/retn[ ]*:[ ]*\@(\d+) /)
3339 {
3340 my $ReturnTypeId = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003341 my %ReturnAttr = getTypeAttr($ReturnTypeId);
3342 if(not $ReturnAttr{"Name"})
3343 { # templates
3344 return ();
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003345 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003346 $MemPtrName .= $ReturnAttr{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003347 $TypeAttr{"Return"} = $ReturnTypeId;
3348 }
3349 }
3350 # Class
3351 if($MemInfo=~/(clas|cls)[ ]*:[ ]*@(\d+) /)
3352 {
3353 $TypeAttr{"Class"} = $2;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003354 my %Class = getTypeAttr($TypeAttr{"Class"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003355 if($Class{"Name"}) {
3356 $MemPtrName .= " (".$Class{"Name"}."\:\:*)";
3357 }
3358 else {
3359 $MemPtrName .= " (*)";
3360 }
3361 }
3362 else {
3363 $MemPtrName .= " (*)";
3364 }
3365 # Parameters
3366 if($Type eq "FuncPtr"
3367 or $Type eq "MethodPtr")
3368 {
3369 my @ParamTypeName = ();
3370 if($MemInfo=~/prms[ ]*:[ ]*@(\d+) /)
3371 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003372 my $PTypeInfoId = $1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003373 my ($Pos, $PPos) = (0, 0);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003374 while($PTypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003375 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003376 my $PTypeInfo = $LibInfo{$Version}{"info"}{$PTypeInfoId};
3377 if($PTypeInfo=~/valu[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003378 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003379 my $PTypeId = $1;
3380 my %ParamAttr = getTypeAttr($PTypeId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003381 if(not $ParamAttr{"Name"})
3382 { # templates (template_type_parm), etc.
3383 return ();
3384 }
3385 if($ParamAttr{"Name"} eq "void") {
3386 last;
3387 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003388 if($Pos!=0 or $Type ne "MethodPtr")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003389 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003390 $TypeAttr{"Param"}{$PPos++}{"type"} = $PTypeId;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003391 push(@ParamTypeName, $ParamAttr{"Name"});
3392 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003393 if($PTypeInfoId = getNextElem($PTypeInfoId)) {
3394 $Pos+=1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003395 }
3396 else {
3397 last;
3398 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003399 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04003400 else {
3401 last;
3402 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003403 }
3404 }
3405 $MemPtrName .= " (".join(", ", @ParamTypeName).")";
3406 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003407 $TypeAttr{"Name"} = formatName($MemPtrName, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003408 return %TypeAttr;
3409}
3410
3411sub getTreeTypeName($)
3412{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003413 my $TypeId = $_[0];
3414 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003415 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003416 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "integer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003417 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003418 if(my $Name = getNameByInfo($TypeId))
3419 { # bit_size_type
3420 return $Name;
3421 }
3422 elsif($Info=~/unsigned/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003423 return "unsigned int";
3424 }
3425 else {
3426 return "int";
3427 }
3428 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04003429 elsif($Info=~/name[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003430 return getNameByInfo($1);
3431 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003432 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003433 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003434}
3435
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003436sub isFuncPtr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003437{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003438 my $Ptd = pointTo($_[0]);
3439 return 0 if(not $Ptd);
3440 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003441 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003442 if($Info=~/unql[ ]*:/ and $Info!~/qual[ ]*:/) {
3443 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003444 }
3445 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003446 if(my $InfoT1 = $LibInfo{$Version}{"info_type"}{$_[0]}
3447 and my $InfoT2 = $LibInfo{$Version}{"info_type"}{$Ptd})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003448 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003449 if($InfoT1 eq "pointer_type"
3450 and $InfoT2 eq "function_type") {
3451 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003452 }
3453 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003454 return 0;
3455}
3456
3457sub isMethodPtr($)
3458{
3459 my $Ptd = pointTo($_[0]);
3460 return 0 if(not $Ptd);
3461 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3462 {
3463 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "record_type"
3464 and $LibInfo{$Version}{"info_type"}{$Ptd} eq "method_type"
3465 and $Info=~/ ptrmem /) {
3466 return 1;
3467 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003468 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003469 return 0;
3470}
3471
3472sub isFieldPtr($)
3473{
3474 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3475 {
3476 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "offset_type"
3477 and $Info=~/ ptrmem /) {
3478 return 1;
3479 }
3480 }
3481 return 0;
3482}
3483
3484sub pointTo($)
3485{
3486 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3487 {
3488 if($Info=~/ptd[ ]*:[ ]*@(\d+)/) {
3489 return $1;
3490 }
3491 }
3492 return "";
3493}
3494
3495sub getTypeTypeByTypeId($)
3496{
3497 my $TypeId = $_[0];
3498 if(my $TType = $LibInfo{$Version}{"info_type"}{$TypeId})
3499 {
3500 my $NType = $NodeType{$TType};
3501 if($NType eq "Intrinsic") {
3502 return $NType;
3503 }
3504 elsif(isFuncPtr($TypeId)) {
3505 return "FuncPtr";
3506 }
3507 elsif(isMethodPtr($TypeId)) {
3508 return "MethodPtr";
3509 }
3510 elsif(isFieldPtr($TypeId)) {
3511 return "FieldPtr";
3512 }
3513 elsif($NType ne "Other") {
3514 return $NType;
3515 }
3516 }
3517 return "Unknown";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003518}
3519
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003520my %UnQual = (
3521 "r"=>"restrict",
3522 "v"=>"volatile",
3523 "c"=>"const",
3524 "cv"=>"const volatile"
3525);
3526
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003527sub getQual($)
3528{
3529 my $TypeId = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003530 if(my $Info = $LibInfo{$Version}{"info"}{$TypeId})
3531 {
3532 my ($Qual, $To) = ();
3533 if($Info=~/qual[ ]*:[ ]*(r|c|v|cv) /) {
3534 $Qual = $UnQual{$1};
3535 }
3536 if($Info=~/unql[ ]*:[ ]*\@(\d+)/) {
3537 $To = $1;
3538 }
3539 if($Qual and $To) {
3540 return ($Qual, $To);
3541 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003542 }
3543 return ();
3544}
3545
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003546sub getQualType($)
3547{
3548 if($_[0] eq "const volatile") {
3549 return "ConstVolatile";
3550 }
3551 return ucfirst($_[0]);
3552}
3553
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003554sub getTypeType($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003555{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003556 my $TypeId = $_[0];
3557 my $TypeDeclId = getTypeDeclId($TypeId);
3558 if(defined $MissedTypedef{$Version}{$TypeId})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003559 { # support for old GCC versions
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003560 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq $TypeDeclId) {
3561 return "Typedef";
3562 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003563 }
3564 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3565 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003566 if(($Qual or $To) and $TypeDeclId
3567 and (getTypeId($TypeDeclId) ne $TypeId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003568 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003569 return getQualType($Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003570 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003571 elsif(not $MissedBase_R{$Version}{$TypeId}
3572 and isTypedef($TypeId)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003573 return "Typedef";
3574 }
3575 elsif($Qual)
3576 { # qualified types
3577 return getQualType($Qual);
3578 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003579
3580 if($Info=~/unql[ ]*:[ ]*\@(\d+)/)
3581 { # typedef struct { ... } name
3582 $TypeTypedef{$Version}{$TypeId} = $1;
3583 }
3584
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003585 my $TypeType = getTypeTypeByTypeId($TypeId);
3586 if($TypeType eq "Struct")
3587 {
3588 if($TypeDeclId
3589 and $LibInfo{$Version}{"info_type"}{$TypeDeclId} eq "template_decl") {
3590 return "Template";
3591 }
3592 }
3593 return $TypeType;
3594}
3595
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003596sub isTypedef($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003597{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003598 if($_[0])
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003599 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003600 if($LibInfo{$Version}{"info_type"}{$_[0]} eq "vector_type")
3601 { # typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
3602 return 0;
3603 }
3604 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
3605 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04003606 if(my $TDid = getTypeDeclId($_[0]))
3607 {
3608 if(getTypeId($TDid) eq $_[0]
3609 and getNameByInfo($TDid))
3610 {
3611 if($Info=~/unql[ ]*:[ ]*\@(\d+) /) {
3612 return $1;
3613 }
3614 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003615 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003616 }
3617 }
3618 return 0;
3619}
3620
3621sub selectBaseType($)
3622{
3623 my $TypeId = $_[0];
3624 if(defined $MissedTypedef{$Version}{$TypeId})
3625 { # add missed typedefs
3626 if($MissedTypedef{$Version}{$TypeId}{"TDid"} eq getTypeDeclId($TypeId)) {
3627 return ($TypeId, "");
3628 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003629 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003630 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
3631 my $InfoType = $LibInfo{$Version}{"info_type"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003632
3633 my $MB_R = $MissedBase_R{$Version}{$TypeId};
3634 my $MB = $MissedBase{$Version}{$TypeId};
3635
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003636 my ($Qual, $To) = getQual($TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003637 if(($Qual or $To) and $Info=~/name[ ]*:[ ]*\@(\d+) /
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003638 and (getTypeId($1) ne $TypeId)
3639 and (not $MB_R or getTypeId($1) ne $MB_R))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003640 { # qualified types (special)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003641 return (getTypeId($1), $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003642 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003643 elsif($MB)
3644 { # add base
3645 return ($MB, "");
3646 }
3647 elsif(not $MB_R and my $Bid = isTypedef($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003648 { # typedefs
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003649 return ($Bid, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003650 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003651 elsif($Qual or $To)
3652 { # qualified types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003653 return ($To, $Qual);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003654 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003655 elsif($InfoType eq "reference_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003656 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003657 if($Info=~/refd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003658 return ($1, "&");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003659 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003660 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003661 elsif($InfoType eq "array_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003662 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003663 if($Info=~/elts[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003664 return ($1, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003665 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003666 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003667 elsif($InfoType eq "pointer_type")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003668 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003669 if($Info=~/ptd[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003670 return ($1, "*");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003671 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003672 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003673
3674 return (0, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003675}
3676
3677sub getSymbolInfo_All()
3678{
3679 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3680 { # reverse order
3681 if($LibInfo{$Version}{"info_type"}{$_} eq "function_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003682 getSymbolInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003683 }
3684 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003685
3686 if($ADD_TMPL_INSTANCES)
3687 {
3688 # templates
3689 foreach my $Sid (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$Version}}))
3690 {
3691 my %Map = ();
3692
3693 if(my $ClassId = $SymbolInfo{$Version}{$Sid}{"Class"})
3694 {
3695 if(defined $TemplateMap{$Version}{$ClassId})
3696 {
3697 foreach (keys(%{$TemplateMap{$Version}{$ClassId}})) {
3698 $Map{$_} = $TemplateMap{$Version}{$ClassId}{$_};
3699 }
3700 }
3701 }
3702
3703 if(defined $TemplateMap{$Version}{$Sid})
3704 {
3705 foreach (keys(%{$TemplateMap{$Version}{$Sid}})) {
3706 $Map{$_} = $TemplateMap{$Version}{$Sid}{$_};
3707 }
3708 }
3709
3710 if(defined $SymbolInfo{$Version}{$Sid}{"Param"})
3711 {
3712 foreach (keys(%{$SymbolInfo{$Version}{$Sid}{"Param"}}))
3713 {
3714 my $PTid = $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"};
3715 $SymbolInfo{$Version}{$Sid}{"Param"}{$_}{"type"} = instType(\%Map, $PTid, $Version);
3716 }
3717 }
3718 if(my $Return = $SymbolInfo{$Version}{$Sid}{"Return"}) {
3719 $SymbolInfo{$Version}{$Sid}{"Return"} = instType(\%Map, $Return, $Version);
3720 }
3721 }
3722 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003723}
3724
3725sub getVarInfo_All()
3726{
3727 foreach (sort {int($b)<=>int($a)} keys(%{$LibInfo{$Version}{"info"}}))
3728 { # reverse order
3729 if($LibInfo{$Version}{"info_type"}{$_} eq "var_decl") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003730 getVarInfo($_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003731 }
3732 }
3733}
3734
3735sub isBuiltIn($) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003736 return ($_[0] and $_[0]=~/\<built\-in\>|\<internal\>|\A\./);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003737}
3738
3739sub getVarInfo($)
3740{
3741 my $InfoId = $_[0];
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003742 if(my $NSid = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003743 {
3744 my $NSInfoType = $LibInfo{$Version}{"info_type"}{$NSid};
3745 if($NSInfoType and $NSInfoType eq "function_decl") {
3746 return;
3747 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003748 }
3749 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
3750 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
3751 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"})) {
3752 delete($SymbolInfo{$Version}{$InfoId});
3753 return;
3754 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003755 my $ShortName = getTreeStr(getTreeAttr_Name($InfoId));
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003756 if(not $ShortName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003757 delete($SymbolInfo{$Version}{$InfoId});
3758 return;
3759 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003760 if($ShortName=~/\Atmp_add_class_\d+\Z/) {
3761 delete($SymbolInfo{$Version}{$InfoId});
3762 return;
3763 }
3764 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = $ShortName;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003765 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
3766 {
3767 if($OSgroup eq "windows")
3768 { # cut the offset
3769 $MnglName=~s/\@\d+\Z//g;
3770 }
3771 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
3772 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003773 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003774 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003775 { # validate mangled name
3776 delete($SymbolInfo{$Version}{$InfoId});
3777 return;
3778 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003779 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003780 and index($ShortName, "_Z")==0)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003781 { # _ZTS, etc.
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003782 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003783 }
3784 if(isPrivateData($SymbolInfo{$Version}{$InfoId}{"MnglName"}))
3785 { # non-public global data
3786 delete($SymbolInfo{$Version}{$InfoId});
3787 return;
3788 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003789 $SymbolInfo{$Version}{$InfoId}{"Data"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003790 if(my $Rid = getTypeId($InfoId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003791 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003792 if(not defined $TypeInfo{$Version}{$Rid}
3793 or not $TypeInfo{$Version}{$Rid}{"Name"})
3794 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003795 delete($SymbolInfo{$Version}{$InfoId});
3796 return;
3797 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003798 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Rid;
3799 my $Val = getDataVal($InfoId, $Rid);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04003800 if(defined $Val) {
3801 $SymbolInfo{$Version}{$InfoId}{"Value"} = $Val;
3802 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003803 }
3804 set_Class_And_Namespace($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003805 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
3806 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003807 if(not defined $TypeInfo{$Version}{$ClassId}
3808 or not $TypeInfo{$Version}{$ClassId}{"Name"})
3809 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003810 delete($SymbolInfo{$Version}{$InfoId});
3811 return;
3812 }
3813 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003814 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
3815 { # extern "C"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003816 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04003817 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003818 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003819 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003820 { # --lang=C option
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003821 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003822 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04003823 if(not $CheckHeadersOnly)
3824 {
3825 if(not $SymbolInfo{$Version}{$InfoId}{"Class"})
3826 {
3827 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}
3828 or not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
3829 {
3830 if(link_symbol($ShortName, $Version, "-Deps"))
3831 { # "const" global data is mangled as _ZL... in the TU dump
3832 # but not mangled when compiling a C shared library
3833 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3834 }
3835 }
3836 }
3837 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003838 if($COMMON_LANGUAGE{$Version} eq "C++")
3839 {
3840 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3841 { # for some symbols (_ZTI) the short name is the mangled name
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003842 if(index($ShortName, "_Z")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003843 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3844 }
3845 }
3846 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3847 { # try to mangle symbol (link with libraries)
3848 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = linkSymbol($InfoId);
3849 }
3850 if($OStarget eq "windows")
3851 {
3852 if(my $Mangled = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
3853 { # link MS C++ symbols from library with GCC symbols from headers
3854 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
3855 }
3856 }
3857 }
3858 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"}) {
3859 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $ShortName;
3860 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003861 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
3862 {
3863 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
3864 { # non-target symbols
3865 delete($SymbolInfo{$Version}{$InfoId});
3866 return;
3867 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003868 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003869 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
3870 {
3871 if(defined $MissedTypedef{$Version}{$Rid})
3872 {
3873 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
3874 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
3875 }
3876 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003877 }
3878 setFuncAccess($InfoId);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003879 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_ZTV")==0) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003880 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
3881 }
3882 if($ShortName=~/\A(_Z|\?)/) {
3883 delete($SymbolInfo{$Version}{$InfoId}{"ShortName"});
3884 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04003885
3886 if($ExtraDump) {
3887 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
3888 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003889}
3890
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003891sub isConstType($$)
3892{
3893 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003894 my %Base = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003895 while(defined $Base{"Type"} and $Base{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04003896 %Base = get_OneStep_BaseType($Base{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003897 }
3898 return ($Base{"Type"} eq "Const");
3899}
3900
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003901sub getTrivialName($$)
3902{
3903 my ($TypeInfoId, $TypeId) = @_;
3904 my %TypeAttr = ();
3905 $TypeAttr{"Name"} = getNameByInfo($TypeInfoId);
3906 if(not $TypeAttr{"Name"}) {
3907 $TypeAttr{"Name"} = getTreeTypeName($TypeId);
3908 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003909 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003910 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003911 $TypeAttr{"Name"}=~s/<(.+)\Z//g; # GCC 3.4.4 add template params to the name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003912 if(isAnon($TypeAttr{"Name"}))
3913 {
3914 my $NameSpaceId = $TypeId;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003915 while(my $NSId = getTreeAttr_Scpe(getTypeDeclId($NameSpaceId)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003916 { # searching for a first not anon scope
3917 if($NSId eq $NameSpaceId) {
3918 last;
3919 }
3920 else
3921 {
3922 $TypeAttr{"NameSpace"} = getNameSpace(getTypeDeclId($TypeId));
3923 if(not $TypeAttr{"NameSpace"}
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003924 or not isAnon($TypeAttr{"NameSpace"})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003925 last;
3926 }
3927 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003928 $NameSpaceId = $NSId;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003929 }
3930 }
3931 else
3932 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04003933 if(my $NameSpaceId = getTreeAttr_Scpe($TypeInfoId))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003934 {
3935 if($NameSpaceId ne $TypeId) {
3936 $TypeAttr{"NameSpace"} = getNameSpace($TypeInfoId);
3937 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003938 }
3939 }
Andrey Ponomarenko2956b972012-11-14 19:16:16 +04003940 if($TypeAttr{"NameSpace"} and not isAnon($TypeAttr{"Name"})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003941 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3942 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003943 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003944 if(isAnon($TypeAttr{"Name"}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04003945 { # anon-struct-header.h-line
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003946 $TypeAttr{"Name"} = "anon-".lc($TypeAttr{"Type"})."-";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003947 $TypeAttr{"Name"} .= $TypeAttr{"Header"}."-".$TypeAttr{"Line"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04003948 if($TypeAttr{"NameSpace"}) {
3949 $TypeAttr{"Name"} = $TypeAttr{"NameSpace"}."::".$TypeAttr{"Name"};
3950 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003951 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04003952 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId}
3953 and getTypeDeclId($TypeId) eq $TypeInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003954 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003955 my @TParams = getTParams($TypeId, "Type");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04003956 $TypeAttr{"Name"} = formatName($TypeAttr{"Name"}."< ".join(", ", @TParams)." >", "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003957 }
3958 return ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"});
3959}
3960
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003961sub getTrivialTypeAttr($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003962{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003963 my $TypeId = $_[0];
3964 my $TypeInfoId = getTypeDeclId($_[0]);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003965
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003966 my %TypeAttr = ();
3967
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003968 if($TemplateDecl{$Version}{$TypeId})
3969 { # template_decl
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003970 $TypeAttr{"Template"} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003971 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04003972
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003973 setTypeAccess($TypeId, \%TypeAttr);
3974 ($TypeAttr{"Header"}, $TypeAttr{"Line"}) = getLocation($TypeInfoId);
3975 if(isBuiltIn($TypeAttr{"Header"}))
3976 {
3977 delete($TypeAttr{"Header"});
3978 delete($TypeAttr{"Line"});
3979 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003980 $TypeAttr{"Type"} = getTypeType($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04003981 ($TypeAttr{"Name"}, $TypeAttr{"NameSpace"}) = getTrivialName($TypeInfoId, $TypeId);
3982 if(not $TypeAttr{"Name"}) {
3983 return ();
3984 }
3985 if(not $TypeAttr{"NameSpace"}) {
3986 delete($TypeAttr{"NameSpace"});
3987 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003988
3989 my $Tmpl = undef;
3990
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003991 if(defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003992 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003993 $Tmpl = $BasicTemplate{$Version}{$TypeId};
3994
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04003995 if(my @TParams = getTParams($TypeId, "Type"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04003996 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04003997 foreach my $Pos (0 .. $#TParams)
3998 {
3999 my $Val = $TParams[$Pos];
4000 $TypeAttr{"TParam"}{$Pos}{"name"} = $Val;
4001
4002 if(not defined $TypeAttr{"Template"})
4003 {
4004 my %Base = get_BaseType($TemplateInstance{$Version}{"Type"}{$TypeId}{$Pos}, $Version);
4005
4006 if($Base{"Type"} eq "TemplateParam"
4007 or defined $Base{"Template"}) {
4008 $TypeAttr{"Template"} = 1;
4009 }
4010 }
4011
4012 if($Tmpl)
4013 {
4014 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
4015 {
4016 $TemplateMap{$Version}{$TypeId}{$Arg} = $Val;
4017
4018 if($Val eq $Arg) {
4019 $TypeAttr{"Template"} = 1;
4020 }
4021 }
4022 }
4023 }
4024
4025 if($Tmpl)
4026 {
4027 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
4028 {
4029 if($Pos>$#TParams)
4030 {
4031 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
4032 $TemplateMap{$Version}{$TypeId}{$Arg} = "";
4033 }
4034 }
4035 }
4036 }
4037
4038 if($ADD_TMPL_INSTANCES)
4039 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004040 if($Tmpl)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004041 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004042 if(my $MainInst = getTreeAttr_Type($Tmpl))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004043 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004044 if(not getTreeAttr_Flds($TypeId))
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004045 {
4046 if(my $Flds = getTreeAttr_Flds($MainInst)) {
4047 $LibInfo{$Version}{"info"}{$TypeId} .= " flds: \@$Flds ";
4048 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04004049 }
4050 if(not getTreeAttr_Binf($TypeId))
4051 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004052 if(my $Binf = getTreeAttr_Binf($MainInst)) {
4053 $LibInfo{$Version}{"info"}{$TypeId} .= " binf: \@$Binf ";
4054 }
4055 }
4056 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004057 }
4058 }
4059 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004060
4061 my $StaticFields = setTypeMemb($TypeId, \%TypeAttr);
4062
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004063 if(my $Size = getSize($TypeId))
4064 {
4065 $Size = $Size/$BYTE_SIZE;
4066 $TypeAttr{"Size"} = "$Size";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004067 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004068 else
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004069 {
4070 if($ExtraDump)
4071 {
4072 if(not defined $TypeAttr{"Memb"}
4073 and not $Tmpl)
4074 { # declaration only
4075 $TypeAttr{"Forward"} = 1;
4076 }
4077 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004078 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004079
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004080 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004081 and ($StaticFields or detect_lang($TypeId)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004082 {
4083 $TypeAttr{"Type"} = "Class";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004084 $TypeAttr{"Copied"} = 1; # default, will be changed in getSymbolInfo()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004085 }
4086 if($TypeAttr{"Type"} eq "Struct"
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004087 or $TypeAttr{"Type"} eq "Class")
4088 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004089 my $Skip = setBaseClasses($TypeId, \%TypeAttr);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004090 if($Skip) {
4091 return ();
4092 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004093 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004094 if(my $Algn = getAlgn($TypeId)) {
4095 $TypeAttr{"Algn"} = $Algn/$BYTE_SIZE;
4096 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004097 setSpec($TypeId, \%TypeAttr);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004098
4099 if($TypeAttr{"Type"}=~/\A(Struct|Union|Enum)\Z/)
4100 {
4101 if(not $TypedefToAnon{$TypeId}
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004102 and not defined $TemplateInstance{$Version}{"Type"}{$TypeId})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004103 {
4104 if(not isAnon($TypeAttr{"Name"})) {
4105 $TypeAttr{"Name"} = lc($TypeAttr{"Type"})." ".$TypeAttr{"Name"};
4106 }
4107 }
4108 }
4109
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004110 $TypeAttr{"Tid"} = $TypeId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004111 if(my $VTable = $ClassVTable_Content{$Version}{$TypeAttr{"Name"}})
4112 {
4113 my @Entries = split(/\n/, $VTable);
4114 foreach (1 .. $#Entries)
4115 {
4116 my $Entry = $Entries[$_];
4117 if($Entry=~/\A(\d+)\s+(.+)\Z/) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004118 $TypeAttr{"VTable"}{$1} = simplifyVTable($2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004119 }
4120 }
4121 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004122
4123 if($TypeAttr{"Type"} eq "Enum")
4124 {
4125 if(not $TypeAttr{"NameSpace"})
4126 {
4127 foreach my $Pos (keys(%{$TypeAttr{"Memb"}}))
4128 {
4129 my $MName = $TypeAttr{"Memb"}{$Pos}{"name"};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004130 my $MVal = $TypeAttr{"Memb"}{$Pos}{"value"};
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004131 $EnumConstants{$Version}{$MName} = {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004132 "Value"=>$MVal,
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004133 "Header"=>$TypeAttr{"Header"}
4134 };
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004135 if(isAnon($TypeAttr{"Name"}))
4136 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004137 if($ExtraDump
4138 or is_target_header($TypeAttr{"Header"}, $Version))
4139 {
4140 %{$Constants{$Version}{$MName}} = (
4141 "Value" => $MVal,
4142 "Header" => $TypeAttr{"Header"}
4143 );
4144 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004145 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004146 }
4147 }
4148 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004149 if($ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004150 {
4151 if(defined $TypedefToAnon{$TypeId}) {
4152 $TypeAttr{"AnonTypedef"} = 1;
4153 }
4154 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04004155
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004156 return %TypeAttr;
4157}
4158
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004159sub simplifyVTable($)
4160{
4161 my $Content = $_[0];
4162 if($Content=~s/ \[with (.+)]//)
4163 { # std::basic_streambuf<_CharT, _Traits>::imbue [with _CharT = char, _Traits = std::char_traits<char>]
4164 if(my @Elems = separate_Params($1, 0, 0))
4165 {
4166 foreach my $Elem (@Elems)
4167 {
4168 if($Elem=~/\A(.+?)\s*=\s*(.+?)\Z/)
4169 {
4170 my ($Arg, $Val) = ($1, $2);
4171
4172 if(defined $DEFAULT_STD_ARGS{$Arg}) {
4173 $Content=~s/,\s*$Arg\b//g;
4174 }
4175 else {
4176 $Content=~s/\b$Arg\b/$Val/g;
4177 }
4178 }
4179 }
4180 }
4181 }
4182
4183 return $Content;
4184}
4185
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004186sub detect_lang($)
4187{
4188 my $TypeId = $_[0];
4189 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004190 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004191 { # GCC 4 fncs-node points to only non-artificial methods
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004192 return ($Info=~/(fncs)[ ]*:[ ]*@(\d+) /);
4193 }
4194 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004195 { # GCC 3
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004196 my $Fncs = getTreeAttr_Fncs($TypeId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004197 while($Fncs)
4198 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004199 if($LibInfo{$Version}{"info"}{$Fncs}!~/artificial/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004200 return 1;
4201 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004202 $Fncs = getTreeAttr_Chan($Fncs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004203 }
4204 }
4205 return 0;
4206}
4207
4208sub setSpec($$)
4209{
4210 my ($TypeId, $TypeAttr) = @_;
4211 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
4212 if($Info=~/\s+spec\s+/) {
4213 $TypeAttr->{"Spec"} = 1;
4214 }
4215}
4216
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004217sub setBaseClasses($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004218{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004219 my ($TypeId, $TypeAttr) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004220 my $Info = $LibInfo{$Version}{"info"}{$TypeId};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004221 if(my $Binf = getTreeAttr_Binf($TypeId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004222 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004223 my $Info = $LibInfo{$Version}{"info"}{$Binf};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004224 my $Pos = 0;
4225 while($Info=~s/(pub|public|prot|protected|priv|private|)[ ]+binf[ ]*:[ ]*@(\d+) //)
4226 {
4227 my ($Access, $BInfoId) = ($1, $2);
4228 my $ClassId = getBinfClassId($BInfoId);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004229 my $CType = $LibInfo{$Version}{"info_type"}{$ClassId};
4230 if(not $CType or $CType eq "template_type_parm"
4231 or $CType eq "typename_type")
4232 { # skip
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04004233 # return 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004234 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004235 my $BaseInfo = $LibInfo{$Version}{"info"}{$BInfoId};
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004236 if($Access=~/prot/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004237 $TypeAttr->{"Base"}{$ClassId}{"access"} = "protected";
4238 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004239 elsif($Access=~/priv/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004240 $TypeAttr->{"Base"}{$ClassId}{"access"} = "private";
4241 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004242 $TypeAttr->{"Base"}{$ClassId}{"pos"} = "$Pos";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004243 if($BaseInfo=~/virt/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004244 { # virtual base
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004245 $TypeAttr->{"Base"}{$ClassId}{"virtual"} = 1;
4246 }
4247 $Class_SubClasses{$Version}{$ClassId}{$TypeId}=1;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04004248 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004249 }
4250 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004251 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004252}
4253
4254sub getBinfClassId($)
4255{
4256 my $Info = $LibInfo{$Version}{"info"}{$_[0]};
4257 $Info=~/type[ ]*:[ ]*@(\d+) /;
4258 return $1;
4259}
4260
4261sub unmangledFormat($$)
4262{
4263 my ($Name, $LibVersion) = @_;
4264 $Name = uncover_typedefs($Name, $LibVersion);
4265 while($Name=~s/([^\w>*])(const|volatile)(,|>|\Z)/$1$3/g){};
4266 $Name=~s/\(\w+\)(\d)/$1/;
4267 return $Name;
4268}
4269
4270sub modelUnmangled($$)
4271{
4272 my ($InfoId, $Compiler) = @_;
4273 if($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId}) {
4274 return $Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId};
4275 }
4276 my $PureSignature = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
4277 if($SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4278 $PureSignature = "~".$PureSignature;
4279 }
4280 if(not $SymbolInfo{$Version}{$InfoId}{"Data"})
4281 {
4282 my (@Params, @ParamTypes) = ();
4283 if(defined $SymbolInfo{$Version}{$InfoId}{"Param"}
4284 and not $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
4285 @Params = keys(%{$SymbolInfo{$Version}{$InfoId}{"Param"}});
4286 }
4287 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4288 { # checking parameters
4289 my $PId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004290 my %PType = get_PureType($PId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004291 my $PTName = unmangledFormat($PType{"Name"}, $Version);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004292 $PTName=~s/\b(restrict|register)\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004293 if($Compiler eq "MSVC") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004294 $PTName=~s/\blong long\b/__int64/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004295 }
4296 @ParamTypes = (@ParamTypes, $PTName);
4297 }
4298 if(@ParamTypes) {
4299 $PureSignature .= "(".join(", ", @ParamTypes).")";
4300 }
4301 else
4302 {
4303 if($Compiler eq "MSVC")
4304 {
4305 $PureSignature .= "(void)";
4306 }
4307 else
4308 { # GCC
4309 $PureSignature .= "()";
4310 }
4311 }
4312 $PureSignature = delete_keywords($PureSignature);
4313 }
4314 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
4315 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004316 my $ClassName = unmangledFormat($TypeInfo{$Version}{$ClassId}{"Name"}, $Version);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004317 $PureSignature = $ClassName."::".$PureSignature;
4318 }
4319 elsif(my $NS = $SymbolInfo{$Version}{$InfoId}{"NameSpace"}) {
4320 $PureSignature = $NS."::".$PureSignature;
4321 }
4322 if($SymbolInfo{$Version}{$InfoId}{"Const"}) {
4323 $PureSignature .= " const";
4324 }
4325 if($SymbolInfo{$Version}{$InfoId}{"Volatile"}) {
4326 $PureSignature .= " volatile";
4327 }
4328 my $ShowReturn = 0;
4329 if($Compiler eq "MSVC"
4330 and $SymbolInfo{$Version}{$InfoId}{"Data"})
4331 {
4332 $ShowReturn=1;
4333 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004334 elsif(defined $TemplateInstance{$Version}{"Func"}{$InfoId}
4335 and keys(%{$TemplateInstance{$Version}{"Func"}{$InfoId}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004336 {
4337 $ShowReturn=1;
4338 }
4339 if($ShowReturn)
4340 { # mangled names for template function specializations include return value
4341 if(my $ReturnId = $SymbolInfo{$Version}{$InfoId}{"Return"})
4342 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04004343 my %RType = get_PureType($ReturnId, $TypeInfo{$Version});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004344 my $ReturnName = unmangledFormat($RType{"Name"}, $Version);
4345 $PureSignature = $ReturnName." ".$PureSignature;
4346 }
4347 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004348 return ($Cache{"modelUnmangled"}{$Version}{$Compiler}{$InfoId} = formatName($PureSignature, "S"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004349}
4350
4351sub mangle_symbol($$$)
4352{ # mangling for simple methods
4353 # see gcc-4.6.0/gcc/cp/mangle.c
4354 my ($InfoId, $LibVersion, $Compiler) = @_;
4355 if($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler}) {
4356 return $Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler};
4357 }
4358 my $Mangled = "";
4359 if($Compiler eq "GCC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004360 $Mangled = mangle_symbol_GCC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004361 }
4362 elsif($Compiler eq "MSVC") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004363 $Mangled = mangle_symbol_MSVC($InfoId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004364 }
4365 return ($Cache{"mangle_symbol"}{$LibVersion}{$InfoId}{$Compiler} = $Mangled);
4366}
4367
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004368sub mangle_symbol_MSVC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004369{
4370 my ($InfoId, $LibVersion) = @_;
4371 return "";
4372}
4373
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004374sub mangle_symbol_GCC($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004375{ # see gcc-4.6.0/gcc/cp/mangle.c
4376 my ($InfoId, $LibVersion) = @_;
4377 my ($Mangled, $ClassId, $NameSpace) = ("_Z", 0, "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004378 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004379 my %Repl = ();# SN_ replacements
4380 if($ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
4381 {
4382 my $MangledClass = mangle_param($ClassId, $LibVersion, \%Repl);
4383 if($MangledClass!~/\AN/) {
4384 $MangledClass = "N".$MangledClass;
4385 }
4386 else {
4387 $MangledClass=~s/E\Z//;
4388 }
4389 if($SymbolInfo{$LibVersion}{$InfoId}{"Volatile"}) {
4390 $MangledClass=~s/\AN/NV/;
4391 }
4392 if($SymbolInfo{$LibVersion}{$InfoId}{"Const"}) {
4393 $MangledClass=~s/\AN/NK/;
4394 }
4395 $Mangled .= $MangledClass;
4396 }
4397 elsif($NameSpace = $SymbolInfo{$LibVersion}{$InfoId}{"NameSpace"})
4398 { # mangled by name due to the absence of structured info
4399 my $MangledNS = mangle_ns($NameSpace, $LibVersion, \%Repl);
4400 if($MangledNS!~/\AN/) {
4401 $MangledNS = "N".$MangledNS;
4402 }
4403 else {
4404 $MangledNS=~s/E\Z//;
4405 }
4406 $Mangled .= $MangledNS;
4407 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004408 my ($ShortName, $TmplParams) = template_Base($SymbolInfo{$LibVersion}{$InfoId}{"ShortName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004409 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004410 if(my @TPos = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004411 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004412 foreach (@TPos) {
4413 push(@TParams, $SymbolInfo{$LibVersion}{$InfoId}{"TParam"}{$_}{"name"});
4414 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004415 }
4416 elsif($TmplParams)
4417 { # remangling mode
4418 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004419 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004420 }
4421 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"}) {
4422 $Mangled .= "C1";
4423 }
4424 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4425 $Mangled .= "D0";
4426 }
4427 elsif($ShortName)
4428 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004429 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4430 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004431 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004432 and isConstType($Return, $LibVersion))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004433 { # "const" global data is mangled as _ZL...
4434 $Mangled .= "L";
4435 }
4436 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004437 if($ShortName=~/\Aoperator(\W.*)\Z/)
4438 {
4439 my $Op = $1;
4440 $Op=~s/\A[ ]+//g;
4441 if(my $OpMngl = $OperatorMangling{$Op}) {
4442 $Mangled .= $OpMngl;
4443 }
4444 else { # conversion operator
4445 $Mangled .= "cv".mangle_param(getTypeIdByName($Op, $LibVersion), $LibVersion, \%Repl);
4446 }
4447 }
4448 else {
4449 $Mangled .= length($ShortName).$ShortName;
4450 }
4451 if(@TParams)
4452 { # templates
4453 $Mangled .= "I";
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04004454 foreach my $TParam (@TParams) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004455 $Mangled .= mangle_template_param($TParam, $LibVersion, \%Repl);
4456 }
4457 $Mangled .= "E";
4458 }
4459 if(not $ClassId and @TParams) {
4460 add_substitution($ShortName, \%Repl, 0);
4461 }
4462 }
4463 if($ClassId or $NameSpace) {
4464 $Mangled .= "E";
4465 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04004466 if(@TParams)
4467 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04004468 if($Return) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004469 $Mangled .= mangle_param($Return, $LibVersion, \%Repl);
4470 }
4471 }
4472 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
4473 {
4474 my @Params = ();
4475 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
4476 and not $SymbolInfo{$LibVersion}{$InfoId}{"Destructor"}) {
4477 @Params = keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
4478 }
4479 foreach my $ParamPos (sort {int($a) <=> int($b)} @Params)
4480 { # checking parameters
4481 my $ParamType_Id = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$ParamPos}{"type"};
4482 $Mangled .= mangle_param($ParamType_Id, $LibVersion, \%Repl);
4483 }
4484 if(not @Params) {
4485 $Mangled .= "v";
4486 }
4487 }
4488 $Mangled = correct_incharge($InfoId, $LibVersion, $Mangled);
4489 $Mangled = write_stdcxx_substitution($Mangled);
4490 if($Mangled eq "_Z") {
4491 return "";
4492 }
4493 return $Mangled;
4494}
4495
4496sub correct_incharge($$$)
4497{
4498 my ($InfoId, $LibVersion, $Mangled) = @_;
4499 if($SymbolInfo{$LibVersion}{$InfoId}{"Constructor"})
4500 {
4501 if($MangledNames{$LibVersion}{$Mangled}) {
4502 $Mangled=~s/C1E/C2E/;
4503 }
4504 }
4505 elsif($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
4506 {
4507 if($MangledNames{$LibVersion}{$Mangled}) {
4508 $Mangled=~s/D0E/D1E/;
4509 }
4510 if($MangledNames{$LibVersion}{$Mangled}) {
4511 $Mangled=~s/D1E/D2E/;
4512 }
4513 }
4514 return $Mangled;
4515}
4516
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004517sub template_Base($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004518{ # NOTE: std::_Vector_base<mysqlpp::mysql_type_info>::_Vector_impl
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004519 # NOTE: operators: >>, <<
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004520 my $Name = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004521 if($Name!~/>\Z/ or $Name!~/</) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004522 return $Name;
4523 }
4524 my $TParams = $Name;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004525 while(my $CPos = find_center($TParams, "<"))
4526 { # search for the last <T>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004527 $TParams = substr($TParams, $CPos);
4528 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004529 if($TParams=~s/\A<(.+)>\Z/$1/) {
4530 $Name=~s/<\Q$TParams\E>\Z//;
4531 }
4532 else
4533 { # error
4534 $TParams = "";
4535 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004536 return ($Name, $TParams);
4537}
4538
4539sub get_sub_ns($)
4540{
4541 my $Name = $_[0];
4542 my @NS = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004543 while(my $CPos = find_center($Name, ":"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004544 {
4545 push(@NS, substr($Name, 0, $CPos));
4546 $Name = substr($Name, $CPos);
4547 $Name=~s/\A:://;
4548 }
4549 return (join("::", @NS), $Name);
4550}
4551
4552sub mangle_ns($$$)
4553{
4554 my ($Name, $LibVersion, $Repl) = @_;
4555 if(my $Tid = $TName_Tid{$LibVersion}{$Name})
4556 {
4557 my $Mangled = mangle_param($Tid, $LibVersion, $Repl);
4558 $Mangled=~s/\AN(.+)E\Z/$1/;
4559 return $Mangled;
4560
4561 }
4562 else
4563 {
4564 my ($MangledNS, $SubNS) = ("", "");
4565 ($SubNS, $Name) = get_sub_ns($Name);
4566 if($SubNS) {
4567 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4568 }
4569 $MangledNS .= length($Name).$Name;
4570 add_substitution($MangledNS, $Repl, 0);
4571 return $MangledNS;
4572 }
4573}
4574
4575sub mangle_param($$$)
4576{
4577 my ($PTid, $LibVersion, $Repl) = @_;
4578 my ($MPrefix, $Mangled) = ("", "");
4579 my %ReplCopy = %{$Repl};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004580 my %BaseType = get_BaseType($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004581 my $BaseType_Name = $BaseType{"Name"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04004582 $BaseType_Name=~s/\A(struct|union|enum) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004583 if(not $BaseType_Name) {
4584 return "";
4585 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004586 my ($ShortName, $TmplParams) = template_Base($BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004587 my $Suffix = get_BaseTypeQual($PTid, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004588 while($Suffix=~s/\s*(const|volatile|restrict)\Z//g){};
4589 while($Suffix=~/(&|\*|const)\Z/)
4590 {
4591 if($Suffix=~s/[ ]*&\Z//) {
4592 $MPrefix .= "R";
4593 }
4594 if($Suffix=~s/[ ]*\*\Z//) {
4595 $MPrefix .= "P";
4596 }
4597 if($Suffix=~s/[ ]*const\Z//)
4598 {
4599 if($MPrefix=~/R|P/
4600 or $Suffix=~/&|\*/) {
4601 $MPrefix .= "K";
4602 }
4603 }
4604 if($Suffix=~s/[ ]*volatile\Z//) {
4605 $MPrefix .= "V";
4606 }
4607 #if($Suffix=~s/[ ]*restrict\Z//) {
4608 #$MPrefix .= "r";
4609 #}
4610 }
4611 if(my $Token = $IntrinsicMangling{$BaseType_Name}) {
4612 $Mangled .= $Token;
4613 }
4614 elsif($BaseType{"Type"}=~/(Class|Struct|Union|Enum)/)
4615 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004616 my @TParams = ();
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004617 if(my @TPos = keys(%{$BaseType{"TParam"}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004618 { # parsing mode
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04004619 foreach (@TPos) {
4620 push(@TParams, $BaseType{"TParam"}{$_}{"name"});
4621 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04004622 }
4623 elsif($TmplParams)
4624 { # remangling mode
4625 # support for old ABI dumps
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04004626 @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004627 }
4628 my $MangledNS = "";
4629 my ($SubNS, $SName) = get_sub_ns($ShortName);
4630 if($SubNS) {
4631 $MangledNS .= mangle_ns($SubNS, $LibVersion, $Repl);
4632 }
4633 $MangledNS .= length($SName).$SName;
4634 if(@TParams) {
4635 add_substitution($MangledNS, $Repl, 0);
4636 }
4637 $Mangled .= "N".$MangledNS;
4638 if(@TParams)
4639 { # templates
4640 $Mangled .= "I";
4641 foreach my $TParam (@TParams) {
4642 $Mangled .= mangle_template_param($TParam, $LibVersion, $Repl);
4643 }
4644 $Mangled .= "E";
4645 }
4646 $Mangled .= "E";
4647 }
4648 elsif($BaseType{"Type"}=~/(FuncPtr|MethodPtr)/)
4649 {
4650 if($BaseType{"Type"} eq "MethodPtr") {
4651 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl)."F";
4652 }
4653 else {
4654 $Mangled .= "PF";
4655 }
4656 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4657 my @Params = keys(%{$BaseType{"Param"}});
4658 foreach my $Num (sort {int($a)<=>int($b)} @Params) {
4659 $Mangled .= mangle_param($BaseType{"Param"}{$Num}{"type"}, $LibVersion, $Repl);
4660 }
4661 if(not @Params) {
4662 $Mangled .= "v";
4663 }
4664 $Mangled .= "E";
4665 }
4666 elsif($BaseType{"Type"} eq "FieldPtr")
4667 {
4668 $Mangled .= "M".mangle_param($BaseType{"Class"}, $LibVersion, $Repl);
4669 $Mangled .= mangle_param($BaseType{"Return"}, $LibVersion, $Repl);
4670 }
4671 $Mangled = $MPrefix.$Mangled;# add prefix (RPK)
4672 if(my $Optimized = write_substitution($Mangled, \%ReplCopy))
4673 {
4674 if($Mangled eq $Optimized)
4675 {
4676 if($ShortName!~/::/)
4677 { # remove "N ... E"
4678 if($MPrefix) {
4679 $Mangled=~s/\A($MPrefix)N(.+)E\Z/$1$2/g;
4680 }
4681 else {
4682 $Mangled=~s/\AN(.+)E\Z/$1/g;
4683 }
4684 }
4685 }
4686 else {
4687 $Mangled = $Optimized;
4688 }
4689 }
4690 add_substitution($Mangled, $Repl, 1);
4691 return $Mangled;
4692}
4693
4694sub mangle_template_param($$$)
4695{ # types + literals
4696 my ($TParam, $LibVersion, $Repl) = @_;
4697 if(my $TPTid = $TName_Tid{$LibVersion}{$TParam}) {
4698 return mangle_param($TPTid, $LibVersion, $Repl);
4699 }
4700 elsif($TParam=~/\A(\d+)(\w+)\Z/)
4701 { # class_name<1u>::method(...)
4702 return "L".$IntrinsicMangling{$ConstantSuffixR{$2}}.$1."E";
4703 }
4704 elsif($TParam=~/\A\(([\w ]+)\)(\d+)\Z/)
4705 { # class_name<(signed char)1>::method(...)
4706 return "L".$IntrinsicMangling{$1}.$2."E";
4707 }
4708 elsif($TParam eq "true")
4709 { # class_name<true>::method(...)
4710 return "Lb1E";
4711 }
4712 elsif($TParam eq "false")
4713 { # class_name<true>::method(...)
4714 return "Lb0E";
4715 }
4716 else { # internal error
4717 return length($TParam).$TParam;
4718 }
4719}
4720
4721sub add_substitution($$$)
4722{
4723 my ($Value, $Repl, $Rec) = @_;
4724 if($Rec)
4725 { # subtypes
4726 my @Subs = ($Value);
4727 while($Value=~s/\A(R|P|K)//) {
4728 push(@Subs, $Value);
4729 }
4730 foreach (reverse(@Subs)) {
4731 add_substitution($_, $Repl, 0);
4732 }
4733 return;
4734 }
4735 return if($Value=~/\AS(\d*)_\Z/);
4736 $Value=~s/\AN(.+)E\Z/$1/g;
4737 return if(defined $Repl->{$Value});
4738 return if(length($Value)<=1);
4739 return if($StdcxxMangling{$Value});
4740 # check for duplicates
4741 my $Base = $Value;
4742 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4743 {
4744 my $Num = $Repl->{$Type};
4745 my $Replace = macro_mangle($Num);
4746 $Base=~s/\Q$Replace\E/$Type/;
4747 }
4748 if(my $OldNum = $Repl->{$Base})
4749 {
4750 $Repl->{$Value} = $OldNum;
4751 return;
4752 }
4753 my @Repls = sort {$b<=>$a} values(%{$Repl});
4754 if(@Repls) {
4755 $Repl->{$Value} = $Repls[0]+1;
4756 }
4757 else {
4758 $Repl->{$Value} = -1;
4759 }
4760 # register duplicates
4761 # upward
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004762 $Base = $Value;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004763 foreach my $Type (sort {$Repl->{$a}<=>$Repl->{$b}} sort keys(%{$Repl}))
4764 {
4765 next if($Base eq $Type);
4766 my $Num = $Repl->{$Type};
4767 my $Replace = macro_mangle($Num);
4768 $Base=~s/\Q$Type\E/$Replace/;
4769 $Repl->{$Base} = $Repl->{$Value};
4770 }
4771}
4772
4773sub macro_mangle($)
4774{
4775 my $Num = $_[0];
4776 if($Num==-1) {
4777 return "S_";
4778 }
4779 else
4780 {
4781 my $Code = "";
4782 if($Num<10)
4783 { # S0_, S1_, S2_, ...
4784 $Code = $Num;
4785 }
4786 elsif($Num>=10 and $Num<=35)
4787 { # SA_, SB_, SC_, ...
4788 $Code = chr(55+$Num);
4789 }
4790 else
4791 { # S10_, S11_, S12_
4792 $Code = $Num-26; # 26 is length of english alphabet
4793 }
4794 return "S".$Code."_";
4795 }
4796}
4797
4798sub write_stdcxx_substitution($)
4799{
4800 my $Mangled = $_[0];
4801 if($StdcxxMangling{$Mangled}) {
4802 return $StdcxxMangling{$Mangled};
4803 }
4804 else
4805 {
4806 my @Repls = keys(%StdcxxMangling);
4807 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4808 foreach my $MangledType (@Repls)
4809 {
4810 my $Replace = $StdcxxMangling{$MangledType};
4811 #if($Mangled!~/$Replace/) {
4812 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4813 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4814 #}
4815 }
4816 }
4817 return $Mangled;
4818}
4819
4820sub write_substitution($$)
4821{
4822 my ($Mangled, $Repl) = @_;
4823 if(defined $Repl->{$Mangled}
4824 and my $MnglNum = $Repl->{$Mangled}) {
4825 $Mangled = macro_mangle($MnglNum);
4826 }
4827 else
4828 {
4829 my @Repls = keys(%{$Repl});
4830 #@Repls = sort {$Repl->{$a}<=>$Repl->{$b}} @Repls;
4831 # FIXME: how to apply replacements? by num or by pos
4832 @Repls = sort {length($b)<=>length($a)} sort {$b cmp $a} @Repls;
4833 foreach my $MangledType (@Repls)
4834 {
4835 my $Replace = macro_mangle($Repl->{$MangledType});
4836 if($Mangled!~/$Replace/) {
4837 $Mangled=~s/N\Q$MangledType\EE/$Replace/g;
4838 $Mangled=~s/\Q$MangledType\E/$Replace/g;
4839 }
4840 }
4841 }
4842 return $Mangled;
4843}
4844
4845sub delete_keywords($)
4846{
4847 my $TypeName = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004848 $TypeName=~s/\b(enum|struct|union|class) //g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004849 return $TypeName;
4850}
4851
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004852sub uncover_typedefs($$)
4853{
4854 my ($TypeName, $LibVersion) = @_;
4855 return "" if(not $TypeName);
4856 if(defined $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName}) {
4857 return $Cache{"uncover_typedefs"}{$LibVersion}{$TypeName};
4858 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004859 my ($TypeName_New, $TypeName_Pre) = (formatName($TypeName, "T"), "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004860 while($TypeName_New ne $TypeName_Pre)
4861 {
4862 $TypeName_Pre = $TypeName_New;
4863 my $TypeName_Copy = $TypeName_New;
4864 my %Words = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004865 while($TypeName_Copy=~s/\b([a-z_]([\w:]*\w|))\b//io)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004866 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004867 if(not $Intrinsic_Keywords{$1}) {
4868 $Words{$1} = 1;
4869 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004870 }
4871 foreach my $Word (keys(%Words))
4872 {
4873 my $BaseType_Name = $Typedef_BaseName{$LibVersion}{$Word};
4874 next if(not $BaseType_Name);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004875 next if($TypeName_New=~/\b(struct|union|enum)\s\Q$Word\E\b/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004876 if($BaseType_Name=~/\([\*]+\)/)
4877 { # FuncPtr
4878 if($TypeName_New=~/\Q$Word\E(.*)\Z/)
4879 {
4880 my $Type_Suffix = $1;
4881 $TypeName_New = $BaseType_Name;
4882 if($TypeName_New=~s/\(([\*]+)\)/($1 $Type_Suffix)/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004883 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004884 }
4885 }
4886 }
4887 else
4888 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004889 if($TypeName_New=~s/\b\Q$Word\E\b/$BaseType_Name/g) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04004890 $TypeName_New = formatName($TypeName_New, "T");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004891 }
4892 }
4893 }
4894 }
4895 return ($Cache{"uncover_typedefs"}{$LibVersion}{$TypeName} = $TypeName_New);
4896}
4897
4898sub isInternal($)
4899{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004900 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
4901 {
4902 if($Info=~/mngl[ ]*:[ ]*@(\d+) /)
4903 {
4904 if($LibInfo{$Version}{"info"}{$1}=~/\*[ ]*INTERNAL[ ]*\*/)
4905 { # _ZN7mysqlpp8DateTimeC1ERKS0_ *INTERNAL*
4906 return 1;
4907 }
4908 }
4909 }
4910 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004911}
4912
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004913sub getDataVal($$)
4914{
4915 my ($InfoId, $TypeId) = @_;
4916 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4917 {
4918 if($Info=~/init[ ]*:[ ]*@(\d+) /)
4919 {
4920 if(defined $LibInfo{$Version}{"info_type"}{$1}
4921 and $LibInfo{$Version}{"info_type"}{$1} eq "nop_expr")
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004922 {
4923 if(my $Nop = getTreeAttr_Op($1))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004924 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004925 if(defined $LibInfo{$Version}{"info_type"}{$Nop}
4926 and $LibInfo{$Version}{"info_type"}{$Nop} eq "addr_expr")
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004927 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04004928 if(my $Addr = getTreeAttr_Op($1)) {
4929 return getInitVal($Addr, $TypeId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004930 }
4931 }
4932 }
4933 }
4934 else {
4935 return getInitVal($1, $TypeId);
4936 }
4937 }
4938 }
4939 return undef;
4940}
4941
4942sub getInitVal($$)
4943{
4944 my ($InfoId, $TypeId) = @_;
4945 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
4946 {
4947 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$InfoId})
4948 {
4949 if($InfoType eq "integer_cst")
4950 {
4951 my $Val = getNodeIntCst($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04004952 if($TypeId and $TypeInfo{$Version}{$TypeId}{"Name"}=~/\Achar(| const)\Z/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004953 { # characters
4954 $Val = chr($Val);
4955 }
4956 return $Val;
4957 }
4958 elsif($InfoType eq "string_cst") {
4959 return getNodeStrCst($InfoId);
4960 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04004961 elsif($InfoType eq "var_decl")
4962 {
4963 if(my $Name = getNodeStrCst(getTreeAttr_Mngl($InfoId))) {
4964 return $Name;
4965 }
4966 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04004967 }
4968 }
4969 return undef;
4970}
4971
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004972sub set_Class_And_Namespace($)
4973{
4974 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004975 if(my $Info = $LibInfo{$Version}{"info"}{$InfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004976 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004977 if($Info=~/scpe[ ]*:[ ]*@(\d+) /)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004978 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04004979 my $NSInfoId = $1;
4980 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
4981 {
4982 if($InfoType eq "namespace_decl") {
4983 $SymbolInfo{$Version}{$InfoId}{"NameSpace"} = getNameSpace($InfoId);
4984 }
4985 elsif($InfoType eq "record_type") {
4986 $SymbolInfo{$Version}{$InfoId}{"Class"} = $NSInfoId;
4987 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04004988 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004989 }
4990 }
4991 if($SymbolInfo{$Version}{$InfoId}{"Class"}
4992 or $SymbolInfo{$Version}{$InfoId}{"NameSpace"})
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004993 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004994 if($COMMON_LANGUAGE{$Version} ne "C++")
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004995 { # skip
4996 return 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04004997 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04004998 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04004999
5000 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005001}
5002
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005003sub debugMangling($)
5004{
5005 my $LibVersion = $_[0];
5006 my %Mangled = ();
5007 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
5008 {
5009 if(my $Mngl = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
5010 {
5011 if($Mngl=~/\A(_Z|\?)/) {
5012 $Mangled{$Mngl}=$InfoId;
5013 }
5014 }
5015 }
5016 translateSymbols(keys(%Mangled), $LibVersion);
5017 foreach my $Mngl (keys(%Mangled))
5018 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005019 my $U1 = modelUnmangled($Mangled{$Mngl}, "GCC");
5020 my $U2 = $tr_name{$Mngl};
5021 if($U1 ne $U2) {
5022 printMsg("INFO", "INCORRECT MANGLING:\n $Mngl\n $U1\n $U2\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005023 }
5024 }
5025}
5026
5027sub linkSymbol($)
5028{ # link symbols from shared libraries
5029 # with the symbols from header files
5030 my $InfoId = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005031 # try to mangle symbol
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005032 if((not check_gcc($GCC_PATH, "4") and $SymbolInfo{$Version}{$InfoId}{"Class"})
5033 or (check_gcc($GCC_PATH, "4") and not $SymbolInfo{$Version}{$InfoId}{"Class"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005034 { # 1. GCC 3.x doesn't mangle class methods names in the TU dump (only functions and global data)
5035 # 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 +04005036 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005037 {
5038 if(my $Mangled = $mangled_name_gcc{modelUnmangled($InfoId, "GCC")}) {
5039 return correct_incharge($InfoId, $Version, $Mangled);
5040 }
5041 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005042 if($CheckHeadersOnly
5043 or not $BinaryOnly)
5044 { # 1. --headers-only mode
5045 # 2. not mangled src-only symbols
5046 if(my $Mangled = mangle_symbol($InfoId, $Version, "GCC")) {
5047 return $Mangled;
5048 }
5049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005050 }
5051 return "";
5052}
5053
5054sub setLanguage($$)
5055{
5056 my ($LibVersion, $Lang) = @_;
5057 if(not $UserLang) {
5058 $COMMON_LANGUAGE{$LibVersion} = $Lang;
5059 }
5060}
5061
5062sub getSymbolInfo($)
5063{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005064 my $InfoId = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005065 if(isInternal($InfoId)) {
5066 return;
5067 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005068 ($SymbolInfo{$Version}{$InfoId}{"Header"}, $SymbolInfo{$Version}{$InfoId}{"Line"}) = getLocation($InfoId);
5069 if(not $SymbolInfo{$Version}{$InfoId}{"Header"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005070 or isBuiltIn($SymbolInfo{$Version}{$InfoId}{"Header"}))
5071 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005072 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005073 return;
5074 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005075 setFuncAccess($InfoId);
5076 setFuncKind($InfoId);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005077 if($SymbolInfo{$Version}{$InfoId}{"PseudoTemplate"})
5078 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005079 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005080 return;
5081 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005082
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005083 $SymbolInfo{$Version}{$InfoId}{"Type"} = getFuncType($InfoId);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005084 if(my $Return = getFuncReturn($InfoId))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005085 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005086 if(not defined $TypeInfo{$Version}{$Return}
5087 or not $TypeInfo{$Version}{$Return}{"Name"})
5088 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005089 delete($SymbolInfo{$Version}{$InfoId});
5090 return;
5091 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005092 $SymbolInfo{$Version}{$InfoId}{"Return"} = $Return;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005093 }
5094 if(my $Rid = $SymbolInfo{$Version}{$InfoId}{"Return"})
5095 {
5096 if(defined $MissedTypedef{$Version}{$Rid})
5097 {
5098 if(my $AddedTid = $MissedTypedef{$Version}{$Rid}{"Tid"}) {
5099 $SymbolInfo{$Version}{$InfoId}{"Return"} = $AddedTid;
5100 }
5101 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005102 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005103 if(not $SymbolInfo{$Version}{$InfoId}{"Return"}) {
5104 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005105 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005106 my $Orig = getFuncOrig($InfoId);
5107 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getFuncShortName($Orig);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005108 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "\._")!=-1)
5109 {
5110 delete($SymbolInfo{$Version}{$InfoId});
5111 return;
5112 }
5113
5114 if(index($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "tmp_add_func")==0)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005115 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005116 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005117 return;
5118 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005119
5120 if(defined $TemplateInstance{$Version}{"Func"}{$Orig})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005121 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005122 my $Tmpl = $BasicTemplate{$Version}{$InfoId};
5123
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005124 my @TParams = getTParams($Orig, "Func");
5125 if(not @TParams)
5126 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005127 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005128 return;
5129 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005130 foreach my $Pos (0 .. $#TParams)
5131 {
5132 my $Val = $TParams[$Pos];
5133 $SymbolInfo{$Version}{$InfoId}{"TParam"}{$Pos}{"name"} = $Val;
5134
5135 if($Tmpl)
5136 {
5137 if(my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos})
5138 {
5139 $TemplateMap{$Version}{$InfoId}{$Arg} = $Val;
5140 }
5141 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005142 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005143
5144 if($Tmpl)
5145 {
5146 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$TemplateArg{$Version}{$Tmpl}}))
5147 {
5148 if($Pos>$#TParams)
5149 {
5150 my $Arg = $TemplateArg{$Version}{$Tmpl}{$Pos};
5151 $TemplateMap{$Version}{$InfoId}{$Arg} = "";
5152 }
5153 }
5154 }
5155
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005156 my $PrmsInLine = join(", ", @TParams);
Andrey Ponomarenko16934472012-03-29 15:37:04 +04005157 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\Aoperator\W+\Z/)
5158 { # operator<< <T>, operator>> <T>
5159 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= " ";
5160 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005161 $SymbolInfo{$Version}{$InfoId}{"ShortName"} .= "<".$PrmsInLine.">";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005162 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = formatName($SymbolInfo{$Version}{$InfoId}{"ShortName"}, "S");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005163 }
5164 else
5165 { # support for GCC 3.4
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005166 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005167 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005168 if(my $MnglName = getTreeStr(getTreeAttr_Mngl($InfoId)))
5169 {
5170 if($OSgroup eq "windows")
5171 { # cut the offset
5172 $MnglName=~s/\@\d+\Z//g;
5173 }
5174 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $MnglName;
5175
5176 # NOTE: mangling of some symbols may change depending on GCC version
5177 # GCC 4.6: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2IT_EERKS_IT_E
5178 # GCC 4.7: _ZN28QExplicitlySharedDataPointerI11QPixmapDataEC2ERKS1_
5179 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005180
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005181 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005182 and index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")!=0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005183 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005184 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005185 return;
5186 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005187 if(not $SymbolInfo{$Version}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005188 { # destructors have an empty parameter list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005189 my $Skip = setFuncParams($InfoId);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005190 if($Skip)
5191 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005192 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005193 return;
5194 }
5195 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005196 if($LibInfo{$Version}{"info"}{$InfoId}=~/ artificial /i) {
5197 $SymbolInfo{$Version}{$InfoId}{"Artificial"} = 1;
5198 }
5199
5200 if(set_Class_And_Namespace($InfoId))
5201 {
5202 delete($SymbolInfo{$Version}{$InfoId});
5203 return;
5204 }
5205
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005206 if(my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
5207 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005208 if(not defined $TypeInfo{$Version}{$ClassId}
5209 or not $TypeInfo{$Version}{$ClassId}{"Name"})
5210 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005211 delete($SymbolInfo{$Version}{$InfoId});
5212 return;
5213 }
5214 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005215 if($LibInfo{$Version}{"info"}{$InfoId}=~/ lang:[ ]*C /i)
5216 { # extern "C"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005217 $SymbolInfo{$Version}{$InfoId}{"Lang"} = "C";
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04005218 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005219 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005220 if($UserLang and $UserLang eq "C")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005221 { # --lang=C option
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005222 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005223 }
5224 if($COMMON_LANGUAGE{$Version} eq "C++")
5225 { # correct mangled & short names
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005226 # C++ or --headers-only mode
5227 if($SymbolInfo{$Version}{$InfoId}{"ShortName"}=~/\A__(comp|base|deleting)_(c|d)tor\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005228 { # support for old GCC versions: reconstruct real names for constructors and destructors
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005229 $SymbolInfo{$Version}{$InfoId}{"ShortName"} = getNameByInfo(getTypeDeclId($SymbolInfo{$Version}{$InfoId}{"Class"}));
5230 $SymbolInfo{$Version}{$InfoId}{"ShortName"}=~s/<.+>\Z//;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005231 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005232 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005233 { # try to mangle symbol (link with libraries)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005234 if(my $Mangled = linkSymbol($InfoId)) {
5235 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005236 }
5237 }
5238 if($OStarget eq "windows")
5239 { # link MS C++ symbols from library with GCC symbols from headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005240 if(my $Mangled1 = $mangled_name{$Version}{modelUnmangled($InfoId, "MSVC")})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005241 { # exported symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005242 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005243 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005244 elsif(my $Mangled2 = mangle_symbol($InfoId, $Version, "MSVC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005245 { # pure virtual symbols
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005246 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $Mangled2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005247 }
5248 }
5249 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005250 else
5251 { # not mangled in C
5252 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5253 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005254 if(not $CheckHeadersOnly
5255 and $SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function"
5256 and not $SymbolInfo{$Version}{$InfoId}{"Class"})
5257 {
5258 my $Incorrect = 0;
5259
5260 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
5261 {
5262 if(index($SymbolInfo{$Version}{$InfoId}{"MnglName"}, "_Z")==0
5263 and not link_symbol($SymbolInfo{$Version}{$InfoId}{"MnglName"}, $Version, "-Deps"))
5264 { # mangled in the TU dump, but not mangled in the library
5265 $Incorrect = 1;
5266 }
5267 }
5268 else
5269 {
5270 if($SymbolInfo{$Version}{$InfoId}{"Lang"} ne "C")
5271 { # all C++ functions are not mangled in the TU dump
5272 $Incorrect = 1;
5273 }
5274 }
5275 if($Incorrect)
5276 {
5277 if(link_symbol($SymbolInfo{$Version}{$InfoId}{"ShortName"}, $Version, "-Deps")) {
5278 $SymbolInfo{$Version}{$InfoId}{"MnglName"} = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5279 }
5280 }
5281 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005282 if(not $SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005283 { # can't detect symbol name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005284 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005285 return;
5286 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005287 if(not $SymbolInfo{$Version}{$InfoId}{"Constructor"}
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04005288 and my $Spec = getVirtSpec($Orig))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005289 { # identify virtual and pure virtual functions
5290 # NOTE: constructors cannot be virtual
5291 # NOTE: in GCC 4.7 D1 destructors have no virtual spec
5292 # in the TU dump, so taking it from the original symbol
5293 if(not ($SymbolInfo{$Version}{$InfoId}{"Destructor"}
5294 and $SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/D2E/))
5295 { # NOTE: D2 destructors are not present in a v-table
5296 $SymbolInfo{$Version}{$InfoId}{$Spec} = 1;
5297 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005298 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005299 if(isInline($InfoId)) {
5300 $SymbolInfo{$Version}{$InfoId}{"InLine"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005301 }
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +04005302 if(hasThrow($InfoId)) {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005303 $SymbolInfo{$Version}{$InfoId}{"Throw"} = 1;
5304 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005305 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5306 and my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005307 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005308 if(not $SymbolInfo{$Version}{$InfoId}{"InLine"}
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +04005309 and not $SymbolInfo{$Version}{$InfoId}{"Artificial"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005310 { # inline or auto-generated constructor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005311 delete($TypeInfo{$Version}{$ClassId}{"Copied"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005312 }
5313 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005314 if(my $Symbol = $SymbolInfo{$Version}{$InfoId}{"MnglName"})
5315 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04005316 if(not $ExtraDump)
5317 {
5318 if(not selectSymbol($Symbol, $SymbolInfo{$Version}{$InfoId}, "Dump", $Version))
5319 { # non-target symbols
5320 delete($SymbolInfo{$Version}{$InfoId});
5321 return;
5322 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005323 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005324 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005325 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Method"
5326 or $SymbolInfo{$Version}{$InfoId}{"Constructor"}
5327 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}
5328 or $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005329 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005330 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}!~/\A(_Z|\?)/)
5331 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005332 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005333 return;
5334 }
5335 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005336 if($SymbolInfo{$Version}{$InfoId}{"MnglName"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005337 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005338 if($MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005339 { # one instance for one mangled name only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005340 delete($SymbolInfo{$Version}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005341 return;
5342 }
5343 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005344 $MangledNames{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005345 }
5346 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005347 if($SymbolInfo{$Version}{$InfoId}{"Constructor"}
5348 or $SymbolInfo{$Version}{$InfoId}{"Destructor"}) {
5349 delete($SymbolInfo{$Version}{$InfoId}{"Return"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005350 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005351 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/
5352 and $SymbolInfo{$Version}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005353 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005354 if($SymbolInfo{$Version}{$InfoId}{"Type"} eq "Function")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005355 { # static methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005356 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005357 }
5358 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005359 if(getFuncLink($InfoId) eq "Static") {
5360 $SymbolInfo{$Version}{$InfoId}{"Static"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005361 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005362 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A(_Z|\?)/)
5363 {
5364 if(my $Unmangled = $tr_name{$SymbolInfo{$Version}{$InfoId}{"MnglName"}})
5365 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04005366 if($Unmangled=~/\.\_\d/)
5367 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005368 delete($SymbolInfo{$Version}{$InfoId});
5369 return;
5370 }
5371 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005372 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005373 delete($SymbolInfo{$Version}{$InfoId}{"Type"});
5374 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(V|)K/) {
5375 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005376 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005377 if($SymbolInfo{$Version}{$InfoId}{"MnglName"}=~/\A_ZN(K|)V/) {
5378 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005379 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04005380
5381 if($WeakSymbols{$Version}{$SymbolInfo{$Version}{$InfoId}{"MnglName"}}) {
5382 $SymbolInfo{$Version}{$InfoId}{"Weak"} = 1;
5383 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005384
5385 if($ExtraDump) {
5386 $SymbolInfo{$Version}{$InfoId}{"Header"} = guessHeader($InfoId);
5387 }
5388}
5389
5390sub guessHeader($)
5391{
5392 my $InfoId = $_[0];
5393 my $ShortName = $SymbolInfo{$Version}{$InfoId}{"ShortName"};
5394 my $ClassId = $SymbolInfo{$Version}{$InfoId}{"Class"};
5395 my $ClassName = $ClassId?get_ShortClass($ClassId, $Version):"";
5396 my $Header = $SymbolInfo{$Version}{$InfoId}{"Header"};
5397 if(my $HPath = $SymbolHeader{$Version}{$ClassName}{$ShortName})
5398 {
5399 if(get_filename($HPath) eq $Header)
5400 {
5401 my $HDir = get_filename(get_dirname($HPath));
5402 if($HDir ne "include"
5403 and $HDir=~/\A[a-z]+\Z/i) {
5404 return join_P($HDir, $Header);
5405 }
5406 }
5407 }
5408 return $Header;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005409}
5410
5411sub isInline($)
5412{ # "body: undefined" in the tree
5413 # -fkeep-inline-functions GCC option should be specified
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005414 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5415 {
5416 if($Info=~/ undefined /i) {
5417 return 0;
5418 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005419 }
5420 return 1;
5421}
5422
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005423sub hasThrow($)
5424{
5425 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5426 {
5427 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5428 return getTreeAttr_Unql($1, "unql");
5429 }
5430 }
5431 return 1;
5432}
5433
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005434sub getTypeId($)
5435{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005436 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5437 {
5438 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5439 return $1;
5440 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005441 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005442 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005443}
5444
5445sub setTypeMemb($$)
5446{
5447 my ($TypeId, $TypeAttr) = @_;
5448 my $TypeType = $TypeAttr->{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005449 my ($Pos, $UnnamedPos) = (0, 0);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005450 my $StaticFields = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005451 if($TypeType eq "Enum")
5452 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005453 my $MInfoId = getTreeAttr_Csts($TypeId);
5454 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005455 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005456 $TypeAttr->{"Memb"}{$Pos}{"value"} = getEnumMembVal($MInfoId);
5457 my $MembName = getTreeStr(getTreeAttr_Purp($MInfoId));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005458 $TypeAttr->{"Memb"}{$Pos}{"name"} = $MembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005459 $EnumMembName_Id{$Version}{getTreeAttr_Valu($MInfoId)} = ($TypeAttr->{"NameSpace"})?$TypeAttr->{"NameSpace"}."::".$MembName:$MembName;
5460 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005461 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005462 }
5463 }
5464 elsif($TypeType=~/\A(Struct|Class|Union)\Z/)
5465 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005466 my $MInfoId = getTreeAttr_Flds($TypeId);
5467 while($MInfoId)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005468 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005469 my $IType = $LibInfo{$Version}{"info_type"}{$MInfoId};
5470 my $MInfo = $LibInfo{$Version}{"info"}{$MInfoId};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005471 if(not $IType or $IType ne "field_decl")
5472 { # search for fields, skip other stuff in the declaration
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005473
5474 if($IType eq "var_decl")
5475 { # static field
5476 $StaticFields = 1;
5477 }
5478
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005479 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005480 next;
5481 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005482 my $StructMembName = getTreeStr(getTreeAttr_Name($MInfoId));
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005483 if(index($StructMembName, "_vptr.")==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005484 { # virtual tables
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04005485 $StructMembName = "_vptr";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005486 }
5487 if(not $StructMembName)
5488 { # unnamed fields
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005489 if(index($TypeAttr->{"Name"}, "_type_info_pseudo")==-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005490 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005491 my $UnnamedTid = getTreeAttr_Type($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005492 my $UnnamedTName = getNameByInfo(getTypeDeclId($UnnamedTid));
5493 if(isAnon($UnnamedTName))
5494 { # rename unnamed fields to unnamed0, unnamed1, ...
5495 $StructMembName = "unnamed".($UnnamedPos++);
5496 }
5497 }
5498 }
5499 if(not $StructMembName)
5500 { # unnamed fields and base classes
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005501 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005502 next;
5503 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005504 my $MembTypeId = getTreeAttr_Type($MInfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005505 if(defined $MissedTypedef{$Version}{$MembTypeId})
5506 {
5507 if(my $AddedTid = $MissedTypedef{$Version}{$MembTypeId}{"Tid"}) {
5508 $MembTypeId = $AddedTid;
5509 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005510 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005511
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005512 $TypeAttr->{"Memb"}{$Pos}{"type"} = $MembTypeId;
5513 $TypeAttr->{"Memb"}{$Pos}{"name"} = $StructMembName;
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005514 if((my $Access = getTreeAccess($MInfoId)) ne "public")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005515 { # marked only protected and private, public by default
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005516 $TypeAttr->{"Memb"}{$Pos}{"access"} = $Access;
5517 }
5518 if($MInfo=~/spec:\s*mutable /)
5519 { # mutable fields
5520 $TypeAttr->{"Memb"}{$Pos}{"mutable"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005521 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005522 if(my $Algn = getAlgn($MInfoId)) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005523 $TypeAttr->{"Memb"}{$Pos}{"algn"} = $Algn;
5524 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005525 if(my $BFSize = getBitField($MInfoId))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005526 { # in bits
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005527 $TypeAttr->{"Memb"}{$Pos}{"bitfield"} = $BFSize;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005528 }
5529 else
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005530 { # in bytes
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005531 if($TypeAttr->{"Memb"}{$Pos}{"algn"}==1)
5532 { # template
5533 delete($TypeAttr->{"Memb"}{$Pos}{"algn"});
5534 }
5535 else {
5536 $TypeAttr->{"Memb"}{$Pos}{"algn"} /= $BYTE_SIZE;
5537 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005538 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04005539
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04005540 $MInfoId = getNextElem($MInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005541 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005542 }
5543 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005544
5545 return $StaticFields;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005546}
5547
5548sub setFuncParams($)
5549{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005550 my $InfoId = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005551 my $ParamInfoId = getTreeAttr_Args($InfoId);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005552 if(getFuncType($InfoId) eq "Method")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005553 { # check type of "this" pointer
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005554 my $ObjectTypeId = getTreeAttr_Type($ParamInfoId);
5555 if(my $ObjectName = $TypeInfo{$Version}{$ObjectTypeId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005556 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005557 if($ObjectName=~/\bconst(| volatile)\*const\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005558 $SymbolInfo{$Version}{$InfoId}{"Const"} = 1;
5559 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005560 if($ObjectName=~/\bvolatile\b/) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005561 $SymbolInfo{$Version}{$InfoId}{"Volatile"} = 1;
5562 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005563 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04005564 else
5565 { # skip
5566 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005567 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +04005568 # skip "this"-parameter
5569 # $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005570 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005571 my ($Pos, $Vtt_Pos) = (0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005572 while($ParamInfoId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005573 { # formal args
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005574 my $ParamTypeId = getTreeAttr_Type($ParamInfoId);
5575 my $ParamName = getTreeStr(getTreeAttr_Name($ParamInfoId));
5576 if(not $ParamName)
5577 { # unnamed
5578 $ParamName = "p".($Pos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005579 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005580 if(defined $MissedTypedef{$Version}{$ParamTypeId})
5581 {
5582 if(my $AddedTid = $MissedTypedef{$Version}{$ParamTypeId}{"Tid"}) {
5583 $ParamTypeId = $AddedTid;
5584 }
5585 }
5586 my $PType = $TypeInfo{$Version}{$ParamTypeId}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005587 if(not $PType or $PType eq "Unknown") {
5588 return 1;
5589 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005590 my $PTName = $TypeInfo{$Version}{$ParamTypeId}{"Name"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005591 if(not $PTName) {
5592 return 1;
5593 }
5594 if($PTName eq "void") {
5595 last;
5596 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005597 if($ParamName eq "__vtt_parm"
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005598 and $TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void const**")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005599 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005600 $Vtt_Pos = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005601 $ParamInfoId = getNextElem($ParamInfoId);
5602 next;
5603 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005604 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005605
5606 if(my %Base = get_BaseType($ParamTypeId, $Version))
5607 {
5608 if(defined $Base{"Template"}) {
5609 return 1;
5610 }
5611 }
5612
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005613 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = $ParamName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005614 if(my $Algn = getAlgn($ParamInfoId)) {
5615 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"algn"} = $Algn/$BYTE_SIZE;
5616 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005617 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"}) {
5618 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($Pos+1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005619 }
5620 if($LibInfo{$Version}{"info"}{$ParamInfoId}=~/spec:\s*register /)
5621 { # foo(register type arg)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005622 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"reg"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005623 }
5624 $ParamInfoId = getNextElem($ParamInfoId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005625 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005626 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005627 if(setFuncArgs($InfoId, $Vtt_Pos)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005628 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = "-1";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005629 }
5630 return 0;
5631}
5632
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005633sub setFuncArgs($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005634{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005635 my ($InfoId, $Vtt_Pos) = @_;
5636 my $FuncTypeId = getFuncTypeId($InfoId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005637 my $ParamListElemId = getTreeAttr_Prms($FuncTypeId);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005638 if(getFuncType($InfoId) eq "Method") {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005639 # $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005640 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005641 if(not $ParamListElemId)
5642 { # foo(...)
5643 return 1;
5644 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005645 my $HaveVoid = 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005646 my $Pos = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005647 while($ParamListElemId)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005648 { # actual params: may differ from formal args
5649 # formal int*const
5650 # actual: int*
5651 if($Vtt_Pos!=-1 and $Pos==$Vtt_Pos)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005652 {
5653 $Vtt_Pos=-1;
5654 $ParamListElemId = getNextElem($ParamListElemId);
5655 next;
5656 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005657 my $ParamTypeId = getTreeAttr_Valu($ParamListElemId);
5658 if($TypeInfo{$Version}{$ParamTypeId}{"Name"} eq "void")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005659 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005660 $HaveVoid = 1;
5661 last;
5662 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005663 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005664 {
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005665 if(not defined $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5666 {
5667 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5668 if(not $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"})
5669 { # unnamed
5670 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"name"} = "p".($Pos+1);
5671 }
5672 }
5673 elsif(my $OldId = $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"})
5674 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04005675 if($Pos>0 or getFuncType($InfoId) ne "Method")
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04005676 { # params
5677 if($OldId ne $ParamTypeId)
5678 {
5679 my %Old_Pure = get_PureType($OldId, $TypeInfo{$Version});
5680 my %New_Pure = get_PureType($ParamTypeId, $TypeInfo{$Version});
5681
5682 if($Old_Pure{"Name"} ne $New_Pure{"Name"}) {
5683 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"type"} = $ParamTypeId;
5684 }
5685 }
5686 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005687 }
5688 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005689 if(my $PurpId = getTreeAttr_Purp($ParamListElemId))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005690 { # default arguments
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005691 if(my $PurpType = $LibInfo{$Version}{"info_type"}{$PurpId})
5692 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005693 if($PurpType eq "nop_expr")
5694 { # func ( const char* arg = (const char*)(void*)0 )
5695 $PurpId = getTreeAttr_Op($PurpId);
5696 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04005697 my $Val = getInitVal($PurpId, $ParamTypeId);
5698 if(defined $Val) {
5699 $SymbolInfo{$Version}{$InfoId}{"Param"}{$Pos}{"default"} = $Val;
5700 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005701 }
5702 }
5703 $ParamListElemId = getNextElem($ParamListElemId);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005704 $Pos += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005705 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04005706 return ($Pos>=1 and not $HaveVoid);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005707}
5708
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005709sub getTreeAttr_Chan($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005710{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005711 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5712 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005713 if($Info=~/chan[ ]*:[ ]*@(\d+) /) {
5714 return $1;
5715 }
5716 }
5717 return "";
5718}
5719
5720sub getTreeAttr_Chain($)
5721{
5722 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5723 {
5724 if($Info=~/chain[ ]*:[ ]*@(\d+) /) {
5725 return $1;
5726 }
5727 }
5728 return "";
5729}
5730
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +04005731sub getTreeAttr_Unql($)
5732{
5733 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5734 {
5735 if($Info=~/unql[ ]*:[ ]*@(\d+) /) {
5736 return $1;
5737 }
5738 }
5739 return "";
5740}
5741
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005742sub getTreeAttr_Scpe($)
5743{
5744 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5745 {
5746 if($Info=~/scpe[ ]*:[ ]*@(\d+) /) {
5747 return $1;
5748 }
5749 }
5750 return "";
5751}
5752
5753sub getTreeAttr_Type($)
5754{
5755 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5756 {
5757 if($Info=~/type[ ]*:[ ]*@(\d+) /) {
5758 return $1;
5759 }
5760 }
5761 return "";
5762}
5763
5764sub getTreeAttr_Name($)
5765{
5766 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5767 {
5768 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
5769 return $1;
5770 }
5771 }
5772 return "";
5773}
5774
5775sub getTreeAttr_Mngl($)
5776{
5777 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5778 {
5779 if($Info=~/mngl[ ]*:[ ]*@(\d+) /) {
5780 return $1;
5781 }
5782 }
5783 return "";
5784}
5785
5786sub getTreeAttr_Prms($)
5787{
5788 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5789 {
5790 if($Info=~/prms[ ]*:[ ]*@(\d+) /) {
5791 return $1;
5792 }
5793 }
5794 return "";
5795}
5796
5797sub getTreeAttr_Fncs($)
5798{
5799 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5800 {
5801 if($Info=~/fncs[ ]*:[ ]*@(\d+) /) {
5802 return $1;
5803 }
5804 }
5805 return "";
5806}
5807
5808sub getTreeAttr_Csts($)
5809{
5810 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5811 {
5812 if($Info=~/csts[ ]*:[ ]*@(\d+) /) {
5813 return $1;
5814 }
5815 }
5816 return "";
5817}
5818
5819sub getTreeAttr_Purp($)
5820{
5821 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5822 {
5823 if($Info=~/purp[ ]*:[ ]*@(\d+) /) {
5824 return $1;
5825 }
5826 }
5827 return "";
5828}
5829
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04005830sub getTreeAttr_Op($)
5831{
5832 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5833 {
5834 if($Info=~/op 0[ ]*:[ ]*@(\d+) /) {
5835 return $1;
5836 }
5837 }
5838 return "";
5839}
5840
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005841sub getTreeAttr_Valu($)
5842{
5843 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5844 {
5845 if($Info=~/valu[ ]*:[ ]*@(\d+) /) {
5846 return $1;
5847 }
5848 }
5849 return "";
5850}
5851
5852sub getTreeAttr_Flds($)
5853{
5854 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5855 {
5856 if($Info=~/flds[ ]*:[ ]*@(\d+) /) {
5857 return $1;
5858 }
5859 }
5860 return "";
5861}
5862
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04005863sub getTreeAttr_Binf($)
5864{
5865 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5866 {
5867 if($Info=~/binf[ ]*:[ ]*@(\d+) /) {
5868 return $1;
5869 }
5870 }
5871 return "";
5872}
5873
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04005874sub getTreeAttr_Args($)
5875{
5876 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5877 {
5878 if($Info=~/args[ ]*:[ ]*@(\d+) /) {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005879 return $1;
5880 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005881 }
5882 return "";
5883}
5884
5885sub getTreeValue($)
5886{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005887 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5888 {
5889 if($Info=~/low[ ]*:[ ]*([^ ]+) /) {
5890 return $1;
5891 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005892 }
5893 return "";
5894}
5895
5896sub getTreeAccess($)
5897{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005898 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005899 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005900 if($Info=~/accs[ ]*:[ ]*([a-zA-Z]+) /)
5901 {
5902 my $Access = $1;
5903 if($Access eq "prot") {
5904 return "protected";
5905 }
5906 elsif($Access eq "priv") {
5907 return "private";
5908 }
5909 }
5910 elsif($Info=~/ protected /)
5911 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005912 return "protected";
5913 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005914 elsif($Info=~/ private /)
5915 { # support for old GCC versions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005916 return "private";
5917 }
5918 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005919 return "public";
5920}
5921
5922sub setFuncAccess($)
5923{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005924 my $Access = getTreeAccess($_[0]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005925 if($Access eq "protected") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005926 $SymbolInfo{$Version}{$_[0]}{"Protected"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005927 }
5928 elsif($Access eq "private") {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04005929 $SymbolInfo{$Version}{$_[0]}{"Private"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005930 }
5931}
5932
5933sub setTypeAccess($$)
5934{
5935 my ($TypeId, $TypeAttr) = @_;
5936 my $Access = getTreeAccess($TypeId);
5937 if($Access eq "protected") {
5938 $TypeAttr->{"Protected"} = 1;
5939 }
5940 elsif($Access eq "private") {
5941 $TypeAttr->{"Private"} = 1;
5942 }
5943}
5944
5945sub setFuncKind($)
5946{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005947 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5948 {
5949 if($Info=~/pseudo tmpl/) {
5950 $SymbolInfo{$Version}{$_[0]}{"PseudoTemplate"} = 1;
5951 }
5952 elsif($Info=~/ constructor /) {
5953 $SymbolInfo{$Version}{$_[0]}{"Constructor"} = 1;
5954 }
5955 elsif($Info=~/ destructor /) {
5956 $SymbolInfo{$Version}{$_[0]}{"Destructor"} = 1;
5957 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005958 }
5959}
5960
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04005961sub getVirtSpec($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005962{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005963 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5964 {
5965 if($Info=~/spec[ ]*:[ ]*pure /) {
5966 return "PureVirt";
5967 }
5968 elsif($Info=~/spec[ ]*:[ ]*virt /) {
5969 return "Virt";
5970 }
5971 elsif($Info=~/ pure\s+virtual /)
5972 { # support for old GCC versions
5973 return "PureVirt";
5974 }
5975 elsif($Info=~/ virtual /)
5976 { # support for old GCC versions
5977 return "Virt";
5978 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005979 }
5980 return "";
5981}
5982
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005983sub getFuncLink($)
5984{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005985 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
5986 {
5987 if($Info=~/link[ ]*:[ ]*static /) {
5988 return "Static";
5989 }
5990 elsif($Info=~/link[ ]*:[ ]*([a-zA-Z]+) /) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005991 return $1;
5992 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005993 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04005994 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005995}
5996
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005997sub select_Symbol_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04005998{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04005999 my ($Symbol, $LibVersion) = @_;
6000 return "" if(not $Symbol or not $LibVersion);
6001 my $NS = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
6002 if(not $NS)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006003 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006004 if(my $Class = $CompleteSignature{$LibVersion}{$Symbol}{"Class"}) {
6005 $NS = $TypeInfo{$LibVersion}{$Class}{"NameSpace"};
6006 }
6007 }
6008 if($NS)
6009 {
6010 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6011 return $NS;
6012 }
6013 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006014 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006015 while($NS=~s/::[^:]+\Z//)
6016 {
6017 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6018 return $NS;
6019 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006020 }
6021 }
6022 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006023
6024 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006025}
6026
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006027sub select_Type_NS($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006028{
6029 my ($TypeName, $LibVersion) = @_;
6030 return "" if(not $TypeName or not $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006031 if(my $NS = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$TypeName}}{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006032 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006033 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6034 return $NS;
6035 }
6036 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006037 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006038 while($NS=~s/::[^:]+\Z//)
6039 {
6040 if(defined $NestedNameSpaces{$LibVersion}{$NS}) {
6041 return $NS;
6042 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006043 }
6044 }
6045 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006046 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006047}
6048
6049sub getNameSpace($)
6050{
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006051 my $InfoId = $_[0];
6052 if(my $NSInfoId = getTreeAttr_Scpe($InfoId))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006053 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006054 if(my $InfoType = $LibInfo{$Version}{"info_type"}{$NSInfoId})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006055 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006056 if($InfoType eq "namespace_decl")
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006057 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006058 if($LibInfo{$Version}{"info"}{$NSInfoId}=~/name[ ]*:[ ]*@(\d+) /)
6059 {
6060 my $NameSpace = getTreeStr($1);
6061 if($NameSpace eq "::")
6062 { # global namespace
6063 return "";
6064 }
6065 if(my $BaseNameSpace = getNameSpace($NSInfoId)) {
6066 $NameSpace = $BaseNameSpace."::".$NameSpace;
6067 }
6068 $NestedNameSpaces{$Version}{$NameSpace} = 1;
6069 return $NameSpace;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006070 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006071 else {
6072 return "";
6073 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006074 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04006075 elsif($InfoType ne "function_decl")
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006076 { # inside data type
6077 my ($Name, $NameNS) = getTrivialName(getTypeDeclId($NSInfoId), $NSInfoId);
6078 return $Name;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006079 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006080 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006081 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006082 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006083}
6084
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006085sub getEnumMembVal($)
6086{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006087 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006088 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006089 if($Info=~/valu[ ]*:[ ]*\@(\d+)/)
6090 {
6091 if(my $VInfo = $LibInfo{$Version}{"info"}{$1})
6092 {
6093 if($VInfo=~/cnst[ ]*:[ ]*\@(\d+)/)
6094 { # in newer versions of GCC the value is in the "const_decl->cnst" node
6095 return getTreeValue($1);
6096 }
6097 else
6098 { # some old versions of GCC (3.3) have the value in the "integer_cst" node
6099 return getTreeValue($1);
6100 }
6101 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006102 }
6103 }
6104 return "";
6105}
6106
6107sub getSize($)
6108{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006109 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6110 {
6111 if($Info=~/size[ ]*:[ ]*\@(\d+)/) {
6112 return getTreeValue($1);
6113 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006114 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006115 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006116}
6117
6118sub getAlgn($)
6119{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006120 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6121 {
6122 if($Info=~/algn[ ]*:[ ]*(\d+) /) {
6123 return $1;
6124 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006125 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006126 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006127}
6128
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04006129sub getBitField($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006130{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006131 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
6132 {
6133 if($Info=~/ bitfield /) {
6134 return getSize($_[0]);
6135 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006136 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006137 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006138}
6139
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006140sub getNextElem($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006141{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006142 if(my $Chan = getTreeAttr_Chan($_[0])) {
6143 return $Chan;
6144 }
6145 elsif(my $Chain = getTreeAttr_Chain($_[0])) {
6146 return $Chain;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006147 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006148 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006149}
6150
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006151sub registerHeader($$)
6152{ # input: absolute path of header, relative path or name
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006153 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006154 if(not $Header) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006155 return "";
6156 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006157 if(is_abs($Header) and not -f $Header)
6158 { # incorrect absolute path
6159 exitStatus("Access_Error", "can't access \'$Header\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006160 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006161 if(skipHeader($Header, $LibVersion))
6162 { # skip
6163 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006164 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006165 if(my $Header_Path = identifyHeader($Header, $LibVersion))
6166 {
6167 detect_header_includes($Header_Path, $LibVersion);
6168
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006169 if(defined $Tolerance and $Tolerance=~/3/)
6170 { # 3 - skip headers that include non-Linux headers
6171 if($OSgroup ne "windows")
6172 {
6173 foreach my $Inc (keys(%{$Header_Includes{$LibVersion}{$Header_Path}}))
6174 {
6175 if(specificHeader($Inc, "windows")) {
6176 return "";
6177 }
6178 }
6179 }
6180 }
6181
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006182 if(my $RHeader_Path = $Header_ErrorRedirect{$LibVersion}{$Header_Path})
6183 { # redirect
6184 if($Registered_Headers{$LibVersion}{$RHeader_Path}{"Identity"}
6185 or skipHeader($RHeader_Path, $LibVersion))
6186 { # skip
6187 return "";
6188 }
6189 $Header_Path = $RHeader_Path;
6190 }
6191 elsif($Header_ShouldNotBeUsed{$LibVersion}{$Header_Path})
6192 { # skip
6193 return "";
6194 }
6195
6196 if(my $HName = get_filename($Header_Path))
6197 { # register
6198 $Registered_Headers{$LibVersion}{$Header_Path}{"Identity"} = $HName;
6199 $HeaderName_Paths{$LibVersion}{$HName}{$Header_Path} = 1;
6200 }
6201
6202 if(($Header=~/\.(\w+)\Z/ and $1 ne "h")
6203 or $Header!~/\.(\w+)\Z/)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006204 { # hpp, hh, etc.
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006205 setLanguage($LibVersion, "C++");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006206 $CPP_HEADERS = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006207 }
6208
6209 if($CheckHeadersOnly
6210 and $Header=~/(\A|\/)c\+\+(\/|\Z)/)
6211 { # /usr/include/c++/4.6.1/...
6212 $STDCXX_TESTING = 1;
6213 }
6214
6215 return $Header_Path;
6216 }
6217 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006218}
6219
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006220sub registerDir($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006221{
6222 my ($Dir, $WithDeps, $LibVersion) = @_;
6223 $Dir=~s/[\/\\]+\Z//g;
6224 return if(not $LibVersion or not $Dir or not -d $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006225 $Dir = get_abs_path($Dir);
6226 my $Mode = "All";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006227 if($WithDeps)
6228 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006229 if($RegisteredDirs{$LibVersion}{$Dir}{1}) {
6230 return;
6231 }
6232 elsif($RegisteredDirs{$LibVersion}{$Dir}{0}) {
6233 $Mode = "DepsOnly";
6234 }
6235 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006236 else
6237 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006238 if($RegisteredDirs{$LibVersion}{$Dir}{1}
6239 or $RegisteredDirs{$LibVersion}{$Dir}{0}) {
6240 return;
6241 }
6242 }
6243 $Header_Dependency{$LibVersion}{$Dir} = 1;
6244 $RegisteredDirs{$LibVersion}{$Dir}{$WithDeps} = 1;
6245 if($Mode eq "DepsOnly")
6246 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006247 foreach my $Path (cmd_find($Dir,"d")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006248 $Header_Dependency{$LibVersion}{$Path} = 1;
6249 }
6250 return;
6251 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006252 foreach my $Path (sort {length($b)<=>length($a)} cmd_find($Dir,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006253 {
6254 if($WithDeps)
6255 {
6256 my $SubDir = $Path;
6257 while(($SubDir = get_dirname($SubDir)) ne $Dir)
6258 { # register all sub directories
6259 $Header_Dependency{$LibVersion}{$SubDir} = 1;
6260 }
6261 }
6262 next if(is_not_header($Path));
6263 next if(ignore_path($Path));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006264 # Neighbors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006265 foreach my $Part (get_prefixes($Path)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006266 $Include_Neighbors{$LibVersion}{$Part} = $Path;
6267 }
6268 }
6269 if(get_filename($Dir) eq "include")
6270 { # search for "lib/include/" directory
6271 my $LibDir = $Dir;
6272 if($LibDir=~s/([\/\\])include\Z/$1lib/g and -d $LibDir) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006273 registerDir($LibDir, $WithDeps, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006274 }
6275 }
6276}
6277
6278sub parse_redirect($$$)
6279{
6280 my ($Content, $Path, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006281 my @Errors = ();
6282 while($Content=~s/#\s*error\s+([^\n]+?)\s*(\n|\Z)//) {
6283 push(@Errors, $1);
6284 }
6285 my $Redirect = "";
6286 foreach (@Errors)
6287 {
6288 s/\s{2,}/ /g;
6289 if(/(only|must\ include
6290 |update\ to\ include
6291 |replaced\ with
6292 |replaced\ by|renamed\ to
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006293 |\ is\ in|\ use)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))/ix)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006294 {
6295 $Redirect = $2;
6296 last;
6297 }
6298 elsif(/(include|use|is\ in)\ (<[^<>]+>|[\w\-\/\\]+\.($HEADER_EXT))\ instead/i)
6299 {
6300 $Redirect = $2;
6301 last;
6302 }
6303 elsif(/this\ header\ should\ not\ be\ used
6304 |programs\ should\ not\ directly\ include
6305 |you\ should\ not\ (include|be\ (including|using)\ this\ (file|header))
6306 |is\ not\ supported\ API\ for\ general\ use
6307 |do\ not\ use
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006308 |should\ not\ be\ (used|using)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006309 |cannot\ be\ included\ directly/ix and not /\ from\ /i) {
6310 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6311 }
6312 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006313 if($Redirect)
6314 {
6315 $Redirect=~s/\A<//g;
6316 $Redirect=~s/>\Z//g;
6317 }
6318 return $Redirect;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006319}
6320
6321sub parse_includes($$)
6322{
6323 my ($Content, $Path) = @_;
6324 my %Includes = ();
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006325 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]*([<"].+?[">])[ \t]*//m)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006326 { # C/C++: include, Objective C/C++: import directive
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04006327 my $Header = $2;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006328 my $Method = substr($Header, 0, 1, "");
6329 substr($Header, length($Header)-1, 1, "");
6330 $Header = path_format($Header, $OSgroup);
6331 if($Method eq "\"" or is_abs($Header))
6332 {
6333 if(-e join_P(get_dirname($Path), $Header))
6334 { # relative path exists
6335 $Includes{$Header} = -1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006336 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006337 else
6338 { # include "..." that doesn't exist is equal to include <...>
6339 $Includes{$Header} = 2;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006340 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006341 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006342 else {
6343 $Includes{$Header} = 1;
6344 }
6345 }
6346 if($ExtraInfo)
6347 {
6348 while($Content=~s/^[ \t]*#[ \t]*(include|include_next|import)[ \t]+(\w+)[ \t]*//m)
6349 { # FT_FREETYPE_H
6350 $Includes{$2} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006351 }
6352 }
6353 return \%Includes;
6354}
6355
6356sub ignore_path($)
6357{
6358 my $Path = $_[0];
6359 if($Path=~/\~\Z/)
6360 {# skipping system backup files
6361 return 1;
6362 }
6363 if($Path=~/(\A|[\/\\]+)(\.(svn|git|bzr|hg)|CVS)([\/\\]+|\Z)/)
6364 {# skipping hidden .svn, .git, .bzr, .hg and CVS directories
6365 return 1;
6366 }
6367 return 0;
6368}
6369
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006370sub sortByWord($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006371{
6372 my ($ArrRef, $W) = @_;
6373 return if(length($W)<2);
6374 @{$ArrRef} = sort {get_filename($b)=~/\Q$W\E/i<=>get_filename($a)=~/\Q$W\E/i} @{$ArrRef};
6375}
6376
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006377sub sortHeaders($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006378{
6379 my ($H1, $H2) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006380
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006381 $H1=~s/\.[a-z]+\Z//ig;
6382 $H2=~s/\.[a-z]+\Z//ig;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006383
6384 my $Hname1 = get_filename($H1);
6385 my $Hname2 = get_filename($H2);
6386 my $HDir1 = get_dirname($H1);
6387 my $HDir2 = get_dirname($H2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006388 my $Dirname1 = get_filename($HDir1);
6389 my $Dirname2 = get_filename($HDir2);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006390
6391 $HDir1=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6392 $HDir2=~s/\A.*[\/\\]+([^\/\\]+[\/\\]+[^\/\\]+)\Z/$1/;
6393
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006394 if($_[0] eq $_[1]
6395 or $H1 eq $H2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006396 return 0;
6397 }
6398 elsif($H1=~/\A\Q$H2\E/) {
6399 return 1;
6400 }
6401 elsif($H2=~/\A\Q$H1\E/) {
6402 return -1;
6403 }
6404 elsif($HDir1=~/\Q$Hname1\E/i
6405 and $HDir2!~/\Q$Hname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006406 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006407 return -1;
6408 }
6409 elsif($HDir2=~/\Q$Hname2\E/i
6410 and $HDir1!~/\Q$Hname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006411 { # include/glib-2.0/glib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006412 return 1;
6413 }
6414 elsif($Hname1=~/\Q$Dirname1\E/i
6415 and $Hname2!~/\Q$Dirname2\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006416 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006417 return -1;
6418 }
6419 elsif($Hname2=~/\Q$Dirname2\E/i
6420 and $Hname1!~/\Q$Dirname1\E/i)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006421 { # include/hildon-thumbnail/hildon-thumbnail-factory.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006422 return 1;
6423 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006424 elsif($Hname1=~/(config|lib|util)/i
6425 and $Hname2!~/(config|lib|util)/i)
6426 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006427 return -1;
6428 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006429 elsif($Hname2=~/(config|lib|util)/i
6430 and $Hname1!~/(config|lib|util)/i)
6431 { # include/alsa/asoundlib.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006432 return 1;
6433 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006434 else
6435 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006436 my $R1 = checkRelevance($H1);
6437 my $R2 = checkRelevance($H2);
6438 if($R1 and not $R2)
6439 { # libebook/e-book.h
6440 return -1;
6441 }
6442 elsif($R2 and not $R1)
6443 { # libebook/e-book.h
6444 return 1;
6445 }
6446 else
6447 {
6448 return (lc($H1) cmp lc($H2));
6449 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006450 }
6451}
6452
6453sub searchForHeaders($)
6454{
6455 my $LibVersion = $_[0];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006456
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006457 # gcc standard include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006458 registerGccHeaders();
6459
6460 if($COMMON_LANGUAGE{$LibVersion} eq "C++" and not $STDCXX_TESTING)
6461 { # c++ standard include paths
6462 registerCppHeaders();
6463 }
6464
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006465 # processing header paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006466 foreach my $Path (@{$Descriptor{$LibVersion}{"IncludePaths"}},
6467 @{$Descriptor{$LibVersion}{"AddIncludePaths"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006468 {
6469 my $IPath = $Path;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006470 if($SystemRoot)
6471 {
6472 if(is_abs($Path)) {
6473 $Path = $SystemRoot.$Path;
6474 }
6475 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006476 if(not -e $Path) {
6477 exitStatus("Access_Error", "can't access \'$Path\'");
6478 }
6479 elsif(-f $Path) {
6480 exitStatus("Access_Error", "\'$Path\' - not a directory");
6481 }
6482 elsif(-d $Path)
6483 {
6484 $Path = get_abs_path($Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006485 registerDir($Path, 0, $LibVersion);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006486 if(grep {$IPath eq $_} @{$Descriptor{$LibVersion}{"AddIncludePaths"}}) {
6487 push(@{$Add_Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006488 }
6489 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006490 push(@{$Include_Paths{$LibVersion}}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006491 }
6492 }
6493 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006494 if(@{$Include_Paths{$LibVersion}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006495 $INC_PATH_AUTODETECT{$LibVersion} = 0;
6496 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006497
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006498 # registering directories
6499 foreach my $Path (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6500 {
6501 next if(not -e $Path);
6502 $Path = get_abs_path($Path);
6503 $Path = path_format($Path, $OSgroup);
6504 if(-d $Path) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006505 registerDir($Path, 1, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006506 }
6507 elsif(-f $Path)
6508 {
6509 my $Dir = get_dirname($Path);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006510 if(not grep { $Dir eq $_ } (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006511 and not $LocalIncludes{$Dir})
6512 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006513 registerDir($Dir, 1, $LibVersion);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006514 # if(my $OutDir = get_dirname($Dir))
6515 # { # registering the outer directory
6516 # if(not grep { $OutDir eq $_ } (@{$SystemPaths{"include"}})
6517 # and not $LocalIncludes{$OutDir}) {
6518 # registerDir($OutDir, 0, $LibVersion);
6519 # }
6520 # }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006521 }
6522 }
6523 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006524
6525 # clean memory
6526 %RegisteredDirs = ();
6527
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006528 # registering headers
6529 my $Position = 0;
6530 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Headers"}))
6531 {
6532 if(is_abs($Dest) and not -e $Dest) {
6533 exitStatus("Access_Error", "can't access \'$Dest\'");
6534 }
6535 $Dest = path_format($Dest, $OSgroup);
6536 if(is_header($Dest, 1, $LibVersion))
6537 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006538 if(my $HPath = registerHeader($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006539 $Registered_Headers{$LibVersion}{$HPath}{"Pos"} = $Position++;
6540 }
6541 }
6542 elsif(-d $Dest)
6543 {
6544 my @Registered = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006545 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006546 {
6547 next if(ignore_path($Path));
6548 next if(not is_header($Path, 0, $LibVersion));
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006549 if(my $HPath = registerHeader($Path, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006550 push(@Registered, $HPath);
6551 }
6552 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006553 @Registered = sort {sortHeaders($a, $b)} @Registered;
6554 sortByWord(\@Registered, $TargetLibraryShortName);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006555 foreach my $Path (@Registered) {
6556 $Registered_Headers{$LibVersion}{$Path}{"Pos"} = $Position++;
6557 }
6558 }
6559 else {
6560 exitStatus("Access_Error", "can't identify \'$Dest\' as a header file");
6561 }
6562 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006563
6564 if(defined $Tolerance and $Tolerance=~/4/)
6565 { # 4 - skip headers included by others
6566 foreach my $Path (keys(%{$Registered_Headers{$LibVersion}}))
6567 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006568 if(defined $Header_Includes_R{$LibVersion}{$Path}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006569 delete($Registered_Headers{$LibVersion}{$Path});
6570 }
6571 }
6572 }
6573
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006574 if(my $HList = $Descriptor{$LibVersion}{"IncludePreamble"})
6575 { # preparing preamble headers
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006576 foreach my $Header (split(/\s*\n\s*/, $HList))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006577 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006578 if(is_abs($Header) and not -f $Header) {
6579 exitStatus("Access_Error", "can't access file \'$Header\'");
6580 }
6581 $Header = path_format($Header, $OSgroup);
6582 if(my $Header_Path = is_header($Header, 1, $LibVersion))
6583 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006584 next if(skipHeader($Header_Path, $LibVersion));
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006585 push_U($Include_Preamble{$LibVersion}, $Header_Path);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04006586 }
6587 else {
6588 exitStatus("Access_Error", "can't identify \'$Header\' as a header file");
6589 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006590 }
6591 }
6592 foreach my $Header_Name (keys(%{$HeaderName_Paths{$LibVersion}}))
6593 { # set relative paths (for duplicates)
6594 if(keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})>=2)
6595 { # search for duplicates
6596 my $FirstPath = (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))[0];
6597 my $Prefix = get_dirname($FirstPath);
6598 while($Prefix=~/\A(.+)[\/\\]+[^\/\\]+\Z/)
6599 { # detect a shortest distinguishing prefix
6600 my $NewPrefix = $1;
6601 my %Identity = ();
6602 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6603 {
6604 if($Path=~/\A\Q$Prefix\E[\/\\]+(.*)\Z/) {
6605 $Identity{$Path} = $1;
6606 }
6607 }
6608 if(keys(%Identity)==keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}}))
6609 { # all names are differend with current prefix
6610 foreach my $Path (keys(%{$HeaderName_Paths{$LibVersion}{$Header_Name}})) {
6611 $Registered_Headers{$LibVersion}{$Path}{"Identity"} = $Identity{$Path};
6612 }
6613 last;
6614 }
6615 $Prefix = $NewPrefix; # increase prefix
6616 }
6617 }
6618 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006619
6620 # clean memory
6621 %HeaderName_Paths = ();
6622
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006623 foreach my $HeaderName (keys(%{$Include_Order{$LibVersion}}))
6624 { # ordering headers according to descriptor
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006625 my $PairName = $Include_Order{$LibVersion}{$HeaderName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006626 my ($Pos, $PairPos) = (-1, -1);
6627 my ($Path, $PairPath) = ();
6628 my @Paths = keys(%{$Registered_Headers{$LibVersion}});
6629 @Paths = sort {int($Registered_Headers{$LibVersion}{$a}{"Pos"})<=>int($Registered_Headers{$LibVersion}{$b}{"Pos"})} @Paths;
6630 foreach my $Header_Path (@Paths)
6631 {
6632 if(get_filename($Header_Path) eq $PairName)
6633 {
6634 $PairPos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6635 $PairPath = $Header_Path;
6636 }
6637 if(get_filename($Header_Path) eq $HeaderName)
6638 {
6639 $Pos = $Registered_Headers{$LibVersion}{$Header_Path}{"Pos"};
6640 $Path = $Header_Path;
6641 }
6642 }
6643 if($PairPos!=-1 and $Pos!=-1
6644 and int($PairPos)<int($Pos))
6645 {
6646 my %Tmp = %{$Registered_Headers{$LibVersion}{$Path}};
6647 %{$Registered_Headers{$LibVersion}{$Path}} = %{$Registered_Headers{$LibVersion}{$PairPath}};
6648 %{$Registered_Headers{$LibVersion}{$PairPath}} = %Tmp;
6649 }
6650 }
6651 if(not keys(%{$Registered_Headers{$LibVersion}})) {
6652 exitStatus("Error", "header files are not found in the ".$Descriptor{$LibVersion}{"Version"});
6653 }
6654}
6655
6656sub detect_real_includes($$)
6657{
6658 my ($AbsPath, $LibVersion) = @_;
6659 return () if(not $LibVersion or not $AbsPath or not -e $AbsPath);
6660 if($Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}
6661 or keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6662 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6663 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006664 $Cache{"detect_real_includes"}{$LibVersion}{$AbsPath}=1;
6665
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006666 my $Path = callPreprocessor($AbsPath, "", $LibVersion);
6667 return () if(not $Path);
6668 open(PREPROC, $Path);
6669 while(<PREPROC>)
6670 {
6671 if(/#\s+\d+\s+"([^"]+)"[\s\d]*\n/)
6672 {
6673 my $Include = path_format($1, $OSgroup);
6674 if($Include=~/\<(built\-in|internal|command(\-|\s)line)\>|\A\./) {
6675 next;
6676 }
6677 if($Include eq $AbsPath) {
6678 next;
6679 }
6680 $RecursiveIncludes{$LibVersion}{$AbsPath}{$Include} = 1;
6681 }
6682 }
6683 close(PREPROC);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006684 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6685}
6686
6687sub detect_header_includes($$)
6688{
6689 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006690 return if(not $LibVersion or not $Path);
6691 if(defined $Cache{"detect_header_includes"}{$LibVersion}{$Path}) {
6692 return;
6693 }
6694 $Cache{"detect_header_includes"}{$LibVersion}{$Path}=1;
6695
6696 if(not -e $Path) {
6697 return;
6698 }
6699
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006700 my $Content = readFile($Path);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006701 if(my $Redirect = parse_redirect($Content, $Path, $LibVersion))
6702 { # detect error directive in headers
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006703 if(my $RedirectPath = identifyHeader($Redirect, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006704 {
6705 if($RedirectPath=~/\/usr\/include\// and $Path!~/\/usr\/include\//) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006706 $RedirectPath = identifyHeader(get_filename($Redirect), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006707 }
6708 if($RedirectPath ne $Path) {
6709 $Header_ErrorRedirect{$LibVersion}{$Path} = $RedirectPath;
6710 }
6711 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006712 else
6713 { # can't find
6714 $Header_ShouldNotBeUsed{$LibVersion}{$Path} = 1;
6715 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006716 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006717 if(my $Inc = parse_includes($Content, $Path))
6718 {
6719 foreach my $Include (keys(%{$Inc}))
6720 { # detect includes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006721 $Header_Includes{$LibVersion}{$Path}{$Include} = $Inc->{$Include};
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006722
6723 if(defined $Tolerance and $Tolerance=~/4/)
6724 {
6725 if(my $HPath = identifyHeader($Include, $LibVersion))
6726 {
6727 $Header_Includes_R{$LibVersion}{$HPath}{$Path} = 1;
6728 }
6729 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006730 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006731 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006732}
6733
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006734sub fromLibc($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006735{ # system GLIBC header
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006736 my $Path = $_[0];
6737 my ($Dir, $Name) = separate_path($Path);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006738 if($OStarget eq "symbian")
6739 {
6740 if(get_filename($Dir) eq "libc" and $GlibcHeader{$Name})
6741 { # epoc32/include/libc/{stdio, ...}.h
6742 return 1;
6743 }
6744 }
6745 else
6746 {
6747 if($Dir eq "/usr/include" and $GlibcHeader{$Name})
6748 { # /usr/include/{stdio, ...}.h
6749 return 1;
6750 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006751 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006752 return 0;
6753}
6754
6755sub isLibcDir($)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006756{ # system GLIBC directory
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006757 my $Dir = $_[0];
6758 my ($OutDir, $Name) = separate_path($Dir);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04006759 if($OStarget eq "symbian")
6760 {
6761 if(get_filename($OutDir) eq "libc"
6762 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6763 { # epoc32/include/libc/{sys,bits,asm,asm-*}/*.h
6764 return 1;
6765 }
6766 }
6767 else
6768 { # linux
6769 if($OutDir eq "/usr/include"
6770 and ($Name=~/\Aasm(|-.+)\Z/ or $GlibcDir{$Name}))
6771 { # /usr/include/{sys,bits,asm,asm-*}/*.h
6772 return 1;
6773 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006774 }
6775 return 0;
6776}
6777
6778sub detect_recursive_includes($$)
6779{
6780 my ($AbsPath, $LibVersion) = @_;
6781 return () if(not $AbsPath);
6782 if(isCyclical(\@RecurInclude, $AbsPath)) {
6783 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6784 }
6785 my ($AbsDir, $Name) = separate_path($AbsPath);
6786 if(isLibcDir($AbsDir))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006787 { # system GLIBC internals
6788 return () if(not $ExtraInfo);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006789 }
6790 if(keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}})) {
6791 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6792 }
6793 return () if($OSgroup ne "windows" and $Name=~/windows|win32|win64/i);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006794
6795 if($MAIN_CPP_DIR and $AbsPath=~/\A\Q$MAIN_CPP_DIR\E/ and not $STDCXX_TESTING)
6796 { # skip /usr/include/c++/*/ headers
6797 return () if(not $ExtraInfo);
6798 }
6799
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006800 push(@RecurInclude, $AbsPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006801 if(grep { $AbsDir eq $_ } @DefaultGccPaths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006802 or (grep { $AbsDir eq $_ } @DefaultIncPaths and fromLibc($AbsPath)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006803 { # check "real" (non-"model") include paths
6804 my @Paths = detect_real_includes($AbsPath, $LibVersion);
6805 pop(@RecurInclude);
6806 return @Paths;
6807 }
6808 if(not keys(%{$Header_Includes{$LibVersion}{$AbsPath}})) {
6809 detect_header_includes($AbsPath, $LibVersion);
6810 }
6811 foreach my $Include (keys(%{$Header_Includes{$LibVersion}{$AbsPath}}))
6812 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006813 my $IncType = $Header_Includes{$LibVersion}{$AbsPath}{$Include};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006814 my $HPath = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006815 if($IncType<0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006816 { # for #include "..."
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006817 my $Candidate = join_P($AbsDir, $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006818 if(-f $Candidate) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006819 $HPath = realpath($Candidate);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006820 }
6821 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006822 elsif($IncType>0
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04006823 and $Include=~/[\/\\]/) # and not find_in_defaults($Include)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006824 { # search for the nearest header
6825 # QtCore/qabstractanimation.h includes <QtCore/qobject.h>
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006826 my $Candidate = join_P(get_dirname($AbsDir), $Include);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006827 if(-f $Candidate) {
6828 $HPath = $Candidate;
6829 }
6830 }
6831 if(not $HPath) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04006832 $HPath = identifyHeader($Include, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006833 }
6834 next if(not $HPath);
6835 if($HPath eq $AbsPath) {
6836 next;
6837 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006838
6839 if($Debug)
6840 { # boundary headers
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04006841# if($HPath=~/vtk/ and $AbsPath!~/vtk/)
6842# {
6843# print STDERR "$AbsPath -> $HPath\n";
6844# }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04006845 }
6846
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006847 $RecursiveIncludes{$LibVersion}{$AbsPath}{$HPath} = $IncType;
6848 if($IncType>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006849 { # only include <...>, skip include "..." prefixes
6850 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$HPath}{get_dirname($Include)} = 1;
6851 }
6852 foreach my $IncPath (detect_recursive_includes($HPath, $LibVersion))
6853 {
6854 if($IncPath eq $AbsPath) {
6855 next;
6856 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04006857 my $RIncType = $RecursiveIncludes{$LibVersion}{$HPath}{$IncPath};
6858 if($RIncType==-1)
6859 { # include "..."
6860 $RIncType = $IncType;
6861 }
6862 elsif($RIncType==2)
6863 {
6864 if($IncType!=-1) {
6865 $RIncType = $IncType;
6866 }
6867 }
6868 $RecursiveIncludes{$LibVersion}{$AbsPath}{$IncPath} = $RIncType;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006869 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$HPath}{$IncPath}})) {
6870 $Header_Include_Prefix{$LibVersion}{$AbsPath}{$IncPath}{$Prefix} = 1;
6871 }
6872 }
6873 foreach my $Dep (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}}))
6874 {
6875 if($GlibcHeader{get_filename($Dep)} and keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}})>=2
6876 and defined $Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""})
6877 { # distinguish math.h from glibc and math.h from the tested library
6878 delete($Header_Include_Prefix{$LibVersion}{$AbsPath}{$Dep}{""});
6879 last;
6880 }
6881 }
6882 }
6883 pop(@RecurInclude);
6884 return keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}});
6885}
6886
6887sub find_in_framework($$$)
6888{
6889 my ($Header, $Framework, $LibVersion) = @_;
6890 return "" if(not $Header or not $Framework or not $LibVersion);
6891 if(defined $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header}) {
6892 return $Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header};
6893 }
6894 foreach my $Dependency (sort {get_depth($a)<=>get_depth($b)} keys(%{$Header_Dependency{$LibVersion}}))
6895 {
6896 if(get_filename($Dependency) eq $Framework
6897 and -f get_dirname($Dependency)."/".$Header) {
6898 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = get_dirname($Dependency));
6899 }
6900 }
6901 return ($Cache{"find_in_framework"}{$LibVersion}{$Framework}{$Header} = "");
6902}
6903
6904sub find_in_defaults($)
6905{
6906 my $Header = $_[0];
6907 return "" if(not $Header);
6908 if(defined $Cache{"find_in_defaults"}{$Header}) {
6909 return $Cache{"find_in_defaults"}{$Header};
6910 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04006911 foreach my $Dir (@DefaultIncPaths,
6912 @DefaultGccPaths,
6913 @DefaultCppPaths,
6914 @UsersIncPath)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006915 {
6916 next if(not $Dir);
6917 if(-f $Dir."/".$Header) {
6918 return ($Cache{"find_in_defaults"}{$Header}=$Dir);
6919 }
6920 }
6921 return ($Cache{"find_in_defaults"}{$Header}="");
6922}
6923
6924sub cmp_paths($$)
6925{
6926 my ($Path1, $Path2) = @_;
6927 my @Parts1 = split(/[\/\\]/, $Path1);
6928 my @Parts2 = split(/[\/\\]/, $Path2);
6929 foreach my $Num (0 .. $#Parts1)
6930 {
6931 my $Part1 = $Parts1[$Num];
6932 my $Part2 = $Parts2[$Num];
6933 if($GlibcDir{$Part1}
6934 and not $GlibcDir{$Part2}) {
6935 return 1;
6936 }
6937 elsif($GlibcDir{$Part2}
6938 and not $GlibcDir{$Part1}) {
6939 return -1;
6940 }
6941 elsif($Part1=~/glib/
6942 and $Part2!~/glib/) {
6943 return 1;
6944 }
6945 elsif($Part1!~/glib/
6946 and $Part2=~/glib/) {
6947 return -1;
6948 }
6949 elsif(my $CmpRes = ($Part1 cmp $Part2)) {
6950 return $CmpRes;
6951 }
6952 }
6953 return 0;
6954}
6955
6956sub checkRelevance($)
6957{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006958 my $Path = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006959 return 0 if(not $Path);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006960
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006961 if($SystemRoot) {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006962 $Path = cut_path_prefix($Path, $SystemRoot);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006963 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006964
6965 my $Name = lc(get_filename($Path));
6966 my $Dir = lc(get_dirname($Path));
6967
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04006968 $Name=~s/\.\w+\Z//g; # remove extension (.h)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006969
6970 foreach my $Token (split(/[_\d\W]+/, $Name))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006971 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04006972 my $Len = length($Token);
6973 next if($Len<=1);
6974 if($Dir=~/(\A|lib|[_\d\W])\Q$Token\E([_\d\W]|lib|\Z)/)
6975 { # include/evolution-data-server-1.4/libebook/e-book.h
6976 return 1;
6977 }
6978 if($Len>=4 and index($Dir, $Token)!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006979 { # include/gupnp-1.0/libgupnp/gupnp-context.h
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04006980 return 1;
6981 }
6982 }
6983 return 0;
6984}
6985
6986sub checkFamily(@)
6987{
6988 my @Paths = @_;
6989 return 1 if($#Paths<=0);
6990 my %Prefix = ();
6991 foreach my $Path (@Paths)
6992 {
6993 if($SystemRoot) {
6994 $Path = cut_path_prefix($Path, $SystemRoot);
6995 }
6996 if(my $Dir = get_dirname($Path))
6997 {
6998 $Dir=~s/(\/[^\/]+?)[\d\.\-\_]+\Z/$1/g; # remove version suffix
6999 $Prefix{$Dir} += 1;
7000 $Prefix{get_dirname($Dir)} += 1;
7001 }
7002 }
7003 foreach (sort keys(%Prefix))
7004 {
7005 if(get_depth($_)>=3
7006 and $Prefix{$_}==$#Paths+1) {
7007 return 1;
7008 }
7009 }
7010 return 0;
7011}
7012
7013sub isAcceptable($$$)
7014{
7015 my ($Header, $Candidate, $LibVersion) = @_;
7016 my $HName = get_filename($Header);
7017 if(get_dirname($Header))
7018 { # with prefix
7019 return 1;
7020 }
7021 if($HName=~/config|setup/i and $Candidate=~/[\/\\]lib\d*[\/\\]/)
7022 { # allow to search for glibconfig.h in /usr/lib/glib-2.0/include/
7023 return 1;
7024 }
7025 if(checkRelevance($Candidate))
7026 { # allow to search for atk.h in /usr/include/atk-1.0/atk/
7027 return 1;
7028 }
7029 if(checkFamily(getSystemHeaders($HName, $LibVersion)))
7030 { # /usr/include/qt4/QtNetwork/qsslconfiguration.h
7031 # /usr/include/qt4/Qt/qsslconfiguration.h
7032 return 1;
7033 }
7034 if($OStarget eq "symbian")
7035 {
7036 if($Candidate=~/[\/\\]stdapis[\/\\]/) {
7037 return 1;
7038 }
7039 }
7040 return 0;
7041}
7042
7043sub isRelevant($$$)
7044{ # disallow to search for "abstract" headers in too deep directories
7045 my ($Header, $Candidate, $LibVersion) = @_;
7046 my $HName = get_filename($Header);
7047 if($OStarget eq "symbian")
7048 {
7049 if($Candidate=~/[\/\\](tools|stlportv5)[\/\\]/) {
7050 return 0;
7051 }
7052 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007053 if($OStarget ne "bsd")
7054 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007055 if($Candidate=~/[\/\\]include[\/\\]bsd[\/\\]/)
7056 { # openssh: skip /usr/lib/bcc/include/bsd/signal.h
7057 return 0;
7058 }
7059 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007060 if($OStarget ne "windows")
7061 {
7062 if($Candidate=~/[\/\\](wine|msvcrt|windows)[\/\\]/)
7063 { # skip /usr/include/wine/msvcrt
7064 return 0;
7065 }
7066 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007067 if(not get_dirname($Header)
7068 and $Candidate=~/[\/\\]wx[\/\\]/)
7069 { # do NOT search in system /wx/ directory
7070 # for headers without a prefix: sstream.h
7071 return 0;
7072 }
7073 if($Candidate=~/c\+\+[\/\\]\d+/ and $MAIN_CPP_DIR
7074 and $Candidate!~/\A\Q$MAIN_CPP_DIR\E/)
7075 { # skip ../c++/3.3.3/ if using ../c++/4.5/
7076 return 0;
7077 }
7078 if($Candidate=~/[\/\\]asm-/
7079 and (my $Arch = getArch($LibVersion)) ne "unknown")
7080 { # arch-specific header files
7081 if($Candidate!~/[\/\\]asm-\Q$Arch\E/)
7082 {# skip ../asm-arm/ if using x86 architecture
7083 return 0;
7084 }
7085 }
7086 my @Candidates = getSystemHeaders($HName, $LibVersion);
7087 if($#Candidates==1)
7088 { # unique header
7089 return 1;
7090 }
7091 my @SCandidates = getSystemHeaders($Header, $LibVersion);
7092 if($#SCandidates==1)
7093 { # unique name
7094 return 1;
7095 }
7096 my $SystemDepth = $SystemRoot?get_depth($SystemRoot):0;
7097 if(get_depth($Candidate)-$SystemDepth>=5)
7098 { # abstract headers in too deep directories
7099 # sstream.h or typeinfo.h in /usr/include/wx-2.9/wx/
7100 if(not isAcceptable($Header, $Candidate, $LibVersion)) {
7101 return 0;
7102 }
7103 }
7104 if($Header eq "parser.h"
7105 and $Candidate!~/\/libxml2\//)
7106 { # select parser.h from xml2 library
7107 return 0;
7108 }
7109 if(not get_dirname($Header)
7110 and keys(%{$SystemHeaders{$HName}})>=3)
7111 { # many headers with the same name
7112 # like thread.h included without a prefix
7113 if(not checkFamily(@Candidates)) {
7114 return 0;
7115 }
7116 }
7117 return 1;
7118}
7119
7120sub selectSystemHeader($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007121{ # cache function
7122 if(defined $Cache{"selectSystemHeader"}{$_[1]}{$_[0]}) {
7123 return $Cache{"selectSystemHeader"}{$_[1]}{$_[0]};
7124 }
7125 return ($Cache{"selectSystemHeader"}{$_[1]}{$_[0]} = selectSystemHeader_I(@_));
7126}
7127
7128sub selectSystemHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007129{
7130 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007131 if(-f $Header) {
7132 return $Header;
7133 }
7134 if(is_abs($Header) and not -f $Header)
7135 { # incorrect absolute path
7136 return "";
7137 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007138 if(defined $ConfHeaders{lc($Header)})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007139 { # too abstract configuration headers
7140 return "";
7141 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007142 my $HName = get_filename($Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007143 if($OSgroup ne "windows")
7144 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007145 if(defined $WinHeaders{lc($HName)}
7146 or $HName=~/windows|win32|win64/i)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007147 { # windows headers
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007148 return "";
7149 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007150 }
7151 if($OSgroup ne "macos")
7152 {
7153 if($HName eq "fp.h")
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007154 { # pngconf.h includes fp.h in Mac OS
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007155 return "";
7156 }
7157 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007158
7159 if(defined $ObsoleteHeaders{$HName})
7160 { # obsolete headers
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007161 return "";
7162 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007163 if($OSgroup eq "linux" or $OSgroup eq "bsd")
7164 {
7165 if(defined $AlienHeaders{$HName}
7166 or defined $AlienHeaders{$Header})
7167 { # alien headers from other systems
7168 return "";
7169 }
7170 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007171
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007172 foreach my $Path (@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007173 { # search in default paths
7174 if(-f $Path."/".$Header) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007175 return join_P($Path,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007176 }
7177 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007178 if(not defined $Cache{"checkSystemFiles"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007179 { # register all headers in system include dirs
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +04007180 checkSystemFiles();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007181 }
7182 foreach my $Candidate (sort {get_depth($a)<=>get_depth($b)}
7183 sort {cmp_paths($b, $a)} getSystemHeaders($Header, $LibVersion))
7184 {
7185 if(isRelevant($Header, $Candidate, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007186 return $Candidate;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007187 }
7188 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007189 # error
7190 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007191}
7192
7193sub getSystemHeaders($$)
7194{
7195 my ($Header, $LibVersion) = @_;
7196 my @Candidates = ();
7197 foreach my $Candidate (sort keys(%{$SystemHeaders{$Header}}))
7198 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007199 if(skipHeader($Candidate, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007200 next;
7201 }
7202 push(@Candidates, $Candidate);
7203 }
7204 return @Candidates;
7205}
7206
7207sub cut_path_prefix($$)
7208{
7209 my ($Path, $Prefix) = @_;
7210 return $Path if(not $Prefix);
7211 $Prefix=~s/[\/\\]+\Z//;
7212 $Path=~s/\A\Q$Prefix\E([\/\\]+|\Z)//;
7213 return $Path;
7214}
7215
7216sub is_default_include_dir($)
7217{
7218 my $Dir = $_[0];
7219 $Dir=~s/[\/\\]+\Z//;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007220 return grep { $Dir eq $_ } (@DefaultGccPaths, @DefaultCppPaths, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007221}
7222
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007223sub identifyHeader($$)
7224{ # cache function
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007225 my ($Header, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007226 if(not $Header) {
7227 return "";
7228 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007229 $Header=~s/\A(\.\.[\\\/])+//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007230 if(defined $Cache{"identifyHeader"}{$LibVersion}{$Header}) {
7231 return $Cache{"identifyHeader"}{$LibVersion}{$Header};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007232 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007233 return ($Cache{"identifyHeader"}{$LibVersion}{$Header} = identifyHeader_I($Header, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007234}
7235
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007236sub identifyHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007237{ # search for header by absolute path, relative path or name
7238 my ($Header, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007239 if(-f $Header)
7240 { # it's relative or absolute path
7241 return get_abs_path($Header);
7242 }
7243 elsif($GlibcHeader{$Header} and not $GLIBC_TESTING
7244 and my $HeaderDir = find_in_defaults($Header))
7245 { # search for libc headers in the /usr/include
7246 # for non-libc target library before searching
7247 # in the library paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007248 return join_P($HeaderDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007249 }
7250 elsif(my $Path = $Include_Neighbors{$LibVersion}{$Header})
7251 { # search in the target library paths
7252 return $Path;
7253 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007254 elsif(defined $DefaultGccHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007255 { # search in the internal GCC include paths
7256 return $DefaultGccHeader{$Header};
7257 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007258 elsif(my $DefaultDir = find_in_defaults($Header))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007259 { # search in the default GCC include paths
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007260 return join_P($DefaultDir,$Header);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007261 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007262 elsif(defined $DefaultCppHeader{$Header})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007263 { # search in the default G++ include paths
7264 return $DefaultCppHeader{$Header};
7265 }
7266 elsif(my $AnyPath = selectSystemHeader($Header, $LibVersion))
7267 { # search everywhere in the system
7268 return $AnyPath;
7269 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007270 elsif($OSgroup eq "macos")
7271 { # search in frameworks: "OpenGL/gl.h" is "OpenGL.framework/Headers/gl.h"
7272 if(my $Dir = get_dirname($Header))
7273 {
7274 my $RelPath = "Headers\/".get_filename($Header);
7275 if(my $HeaderDir = find_in_framework($RelPath, $Dir.".framework", $LibVersion)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007276 return join_P($HeaderDir, $RelPath);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007277 }
7278 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007279 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007280 # cannot find anything
7281 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007282}
7283
7284sub getLocation($)
7285{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007286 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7287 {
7288 if($Info=~/srcp[ ]*:[ ]*([\w\-\<\>\.\+\/\\]+):(\d+) /) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007289 return (path_format($1, $OSgroup), $2);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007290 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007291 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007292 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007293}
7294
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007295sub getNameByInfo($)
7296{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007297 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007298 {
7299 if($Info=~/name[ ]*:[ ]*@(\d+) /)
7300 {
7301 if(my $NInfo = $LibInfo{$Version}{"info"}{$1})
7302 {
7303 if($NInfo=~/strg[ ]*:[ ]*(.*?)[ ]+lngt/)
7304 { # short unsigned int (may include spaces)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007305 my $Str = $1;
7306 if($CppMode{$Version}
7307 and $Str=~/\Ac99_(.+)\Z/)
7308 {
7309 if($CppKeywords_A{$1}) {
7310 $Str=$1;
7311 }
7312 }
7313 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007314 }
7315 }
7316 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007317 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007318 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007319}
7320
7321sub getTreeStr($)
7322{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007323 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007324 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007325 if($Info=~/strg[ ]*:[ ]*([^ ]*)/)
7326 {
7327 my $Str = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007328 if($CppMode{$Version}
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007329 and $Str=~/\Ac99_(.+)\Z/)
7330 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007331 if($CppKeywords_A{$1}) {
7332 $Str=$1;
7333 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007334 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007335 return $Str;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007336 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007337 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007338 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007339}
7340
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007341sub getFuncShortName($)
7342{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007343 if(my $Info = $LibInfo{$Version}{"info"}{$_[0]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007344 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007345 if(index($Info, " operator ")!=-1)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007346 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007347 if(index($Info, " conversion ")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007348 {
7349 if(my $Rid = $SymbolInfo{$Version}{$_[0]}{"Return"})
7350 {
7351 if(my $RName = $TypeInfo{$Version}{$Rid}{"Name"}) {
7352 return "operator ".$RName;
7353 }
7354 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007355 }
7356 else
7357 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007358 if($Info=~/ operator[ ]+([a-zA-Z]+) /)
7359 {
7360 if(my $Ind = $Operator_Indication{$1}) {
7361 return "operator".$Ind;
7362 }
7363 elsif(not $UnknownOperator{$1})
7364 {
7365 printMsg("WARNING", "unknown operator $1");
7366 $UnknownOperator{$1} = 1;
7367 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007368 }
7369 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007370 }
7371 else
7372 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007373 if($Info=~/name[ ]*:[ ]*@(\d+) /) {
7374 return getTreeStr($1);
7375 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007376 }
7377 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007378 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007379}
7380
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007381sub getFuncReturn($)
7382{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007383 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7384 {
7385 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7386 {
7387 if($LibInfo{$Version}{"info"}{$1}=~/retn[ ]*:[ ]*@(\d+) /) {
7388 return $1;
7389 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007390 }
7391 }
7392 return "";
7393}
7394
7395sub getFuncOrig($)
7396{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007397 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7398 {
7399 if($Info=~/orig[ ]*:[ ]*@(\d+) /) {
7400 return $1;
7401 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007402 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007403 return $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007404}
7405
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007406sub unmangleArray(@)
7407{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04007408 if($_[0]=~/\A\?/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007409 { # MSVC mangling
7410 my $UndNameCmd = get_CmdPath("undname");
7411 if(not $UndNameCmd) {
7412 exitStatus("Not_Found", "can't find \"undname\"");
7413 }
7414 writeFile("$TMP_DIR/unmangle", join("\n", @_));
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04007415 return split(/\n/, `$UndNameCmd 0x8386 \"$TMP_DIR/unmangle\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007416 }
7417 else
7418 { # GCC mangling
7419 my $CppFiltCmd = get_CmdPath("c++filt");
7420 if(not $CppFiltCmd) {
7421 exitStatus("Not_Found", "can't find c++filt in PATH");
7422 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007423 if(not defined $CPPFILT_SUPPORT_FILE)
7424 {
7425 my $Info = `$CppFiltCmd -h 2>&1`;
7426 $CPPFILT_SUPPORT_FILE = $Info=~/\@<file>/;
7427 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007428 my $NoStrip = ($OSgroup=~/macos|windows/)?"-n":"";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007429 if($CPPFILT_SUPPORT_FILE)
7430 { # new versions of c++filt can take a file
7431 if($#_>$MAX_CPPFILT_FILE_SIZE)
7432 { # c++filt <= 2.22 may crash on large files (larger than 8mb)
7433 # this is fixed in the oncoming version of Binutils
7434 my @Half = splice(@_, 0, ($#_+1)/2);
7435 return (unmangleArray(@Half), unmangleArray(@_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007436 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007437 else
7438 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007439 writeFile("$TMP_DIR/unmangle", join("\n", @_));
7440 my $Res = `$CppFiltCmd $NoStrip \@\"$TMP_DIR/unmangle\"`;
7441 if($?==139)
7442 { # segmentation fault
7443 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_CPPFILT_FILE_SIZE constant");
7444 }
7445 return split(/\n/, $Res);
7446 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007447 }
7448 else
7449 { # old-style unmangling
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007450 if($#_>$MAX_COMMAND_LINE_ARGUMENTS)
7451 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007452 my @Half = splice(@_, 0, ($#_+1)/2);
7453 return (unmangleArray(@Half), unmangleArray(@_))
7454 }
7455 else
7456 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007457 my $Strings = join(" ", @_);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007458 my $Res = `$CppFiltCmd $NoStrip $Strings`;
7459 if($?==139)
7460 { # segmentation fault
7461 printMsg("ERROR", "internal error - c++filt crashed, try to reduce MAX_COMMAND_LINE_ARGUMENTS constant");
7462 }
7463 return split(/\n/, $Res);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007464 }
7465 }
7466 }
7467}
7468
7469sub get_SignatureNoInfo($$)
7470{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007471 my ($Symbol, $LibVersion) = @_;
7472 if($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol}) {
7473 return $Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007474 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007475 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007476 my $Signature = $tr_name{$MnglName}?$tr_name{$MnglName}:$MnglName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007477 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007478 { # C++
Andrey Ponomarenko1477d2c2012-11-12 18:55:45 +04007479 # some standard typedefs
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007480 $Signature=~s/\Qstd::basic_string<char, std::char_traits<char>, std::allocator<char> >\E/std::string/g;
7481 $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;
7482 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04007483 if(not $CheckObjectsOnly or $OSgroup=~/linux|bsd|beos/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007484 { # ELF format marks data as OBJECT
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007485 if($GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007486 $Signature .= " [data]";
7487 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007488 elsif($Symbol!~/\A(_Z|\?)/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007489 $Signature .= " (...)";
7490 }
7491 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007492 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007493 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04007494 my $ShortName = substr($Signature, 0, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007495 $Signature=~s/\A\Q$ShortName\E/$ShortName $ChargeLevel/g;
7496 }
7497 if($SymbolVersion) {
7498 $Signature .= $VersionSpec.$SymbolVersion;
7499 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007500 return ($Cache{"get_SignatureNoInfo"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007501}
7502
7503sub get_ChargeLevel($$)
7504{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007505 my ($Symbol, $LibVersion) = @_;
7506 return "" if($Symbol!~/\A(_Z|\?)/);
7507 if(defined $CompleteSignature{$LibVersion}{$Symbol}
7508 and $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007509 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007510 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007511 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007512 if($Symbol=~/C1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007513 return "[in-charge]";
7514 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007515 elsif($Symbol=~/C2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007516 return "[not-in-charge]";
7517 }
7518 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007519 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007520 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007521 if($Symbol=~/D1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007522 return "[in-charge]";
7523 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007524 elsif($Symbol=~/D2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007525 return "[not-in-charge]";
7526 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007527 elsif($Symbol=~/D0E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007528 return "[in-charge-deleting]";
7529 }
7530 }
7531 }
7532 else
7533 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007534 if($Symbol=~/C1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007535 return "[in-charge]";
7536 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007537 elsif($Symbol=~/C2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007538 return "[not-in-charge]";
7539 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007540 elsif($Symbol=~/D1E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007541 return "[in-charge]";
7542 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007543 elsif($Symbol=~/D2E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007544 return "[not-in-charge]";
7545 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007546 elsif($Symbol=~/D0E/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007547 return "[in-charge-deleting]";
7548 }
7549 }
7550 return "";
7551}
7552
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007553sub get_Signature_M($$)
7554{
7555 my ($Symbol, $LibVersion) = @_;
7556 my $Signature_M = $tr_name{$Symbol};
7557 if(my $RTid = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
7558 { # add return type name
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007559 $Signature_M = $TypeInfo{$LibVersion}{$RTid}{"Name"}." ".$Signature_M;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007560 }
7561 return $Signature_M;
7562}
7563
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007564sub get_Signature($$)
7565{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007566 my ($Symbol, $LibVersion) = @_;
7567 if($Cache{"get_Signature"}{$LibVersion}{$Symbol}) {
7568 return $Cache{"get_Signature"}{$LibVersion}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007569 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007570 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
7571 if(isPrivateData($MnglName) or not $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04007572 { # non-public global data
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007573 return get_SignatureNoInfo($Symbol, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007574 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007575 my ($Signature, @Param_Types_FromUnmangledName) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007576 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
7577 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007578 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007579 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
7580 {
7581 $Signature .= $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::";
7582 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}) {
7583 $Signature .= "~";
7584 }
7585 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007586 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007587 elsif(my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007588 $Signature .= $NameSpace."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007589 }
7590 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007591 $Signature .= $ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007592 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04007593 my ($Short, $Params) = split_Signature($tr_name{$MnglName});
7594 @Param_Types_FromUnmangledName = separate_Params($Params, 0, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007595 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04007596 else
7597 {
7598 $Signature .= $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007599 }
7600 my @ParamArray = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007601 foreach my $Pos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007602 {
7603 next if($Pos eq "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007604 my $ParamTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007605 next if(not $ParamTypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007606 my $ParamTypeName = $TypeInfo{$LibVersion}{$ParamTypeId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007607 if(not $ParamTypeName) {
7608 $ParamTypeName = $Param_Types_FromUnmangledName[$Pos];
7609 }
7610 foreach my $Typedef (keys(%ChangedTypedef))
7611 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007612 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
7613 $ParamTypeName=~s/\b\Q$Typedef\E\b/$Base/g;
7614 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007615 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04007616 if(my $ParamName = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"name"})
7617 {
7618 if($ParamName ne "this" or $Symbol!~/\A(_Z|\?)/)
7619 { # do NOT show first hidded "this"-parameter
7620 push(@ParamArray, create_member_decl($ParamTypeName, $ParamName));
7621 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007622 }
7623 else {
7624 push(@ParamArray, $ParamTypeName);
7625 }
7626 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007627 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"}
7628 or $GlobalDataObject{$LibVersion}{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007629 $Signature .= " [data]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007630 }
7631 else
7632 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007633 if(my $ChargeLevel = get_ChargeLevel($Symbol, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007634 { # add [in-charge]
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007635 $Signature .= " ".$ChargeLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007636 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007637 $Signature .= " (".join(", ", @ParamArray).")";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007638 if($CompleteSignature{$LibVersion}{$Symbol}{"Const"}
7639 or $Symbol=~/\A_ZN(V|)K/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007640 $Signature .= " const";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007641 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007642 if($CompleteSignature{$LibVersion}{$Symbol}{"Volatile"}
7643 or $Symbol=~/\A_ZN(K|)V/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007644 $Signature .= " volatile";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007645 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007646 if($CompleteSignature{$LibVersion}{$Symbol}{"Static"}
7647 and $Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007648 { # for static methods
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007649 $Signature .= " [static]";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007650 }
7651 }
7652 if(defined $ShowRetVal
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007653 and my $ReturnTId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007654 $Signature .= ":".$TypeInfo{$LibVersion}{$ReturnTId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007655 }
7656 if($SymbolVersion) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007657 $Signature .= $VersionSpec.$SymbolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007658 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04007659 return ($Cache{"get_Signature"}{$LibVersion}{$Symbol} = $Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007660}
7661
7662sub create_member_decl($$)
7663{
7664 my ($TName, $Member) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007665 if($TName=~/\([\*]+\)/)
7666 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007667 $TName=~s/\(([\*]+)\)/\($1$Member\)/;
7668 return $TName;
7669 }
7670 else
7671 {
7672 my @ArraySizes = ();
7673 while($TName=~s/(\[[^\[\]]*\])\Z//) {
7674 push(@ArraySizes, $1);
7675 }
7676 return $TName." ".$Member.join("", @ArraySizes);
7677 }
7678}
7679
7680sub getFuncType($)
7681{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007682 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7683 {
7684 if($Info=~/type[ ]*:[ ]*@(\d+) /)
7685 {
7686 if(my $Type = $LibInfo{$Version}{"info_type"}{$1})
7687 {
7688 if($Type eq "method_type") {
7689 return "Method";
7690 }
7691 elsif($Type eq "function_type") {
7692 return "Function";
7693 }
7694 else {
7695 return "Other";
7696 }
7697 }
7698 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007699 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007700 return "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007701}
7702
7703sub getFuncTypeId($)
7704{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007705 if($_[0] and my $Info = $LibInfo{$Version}{"info"}{$_[0]})
7706 {
7707 if($Info=~/type[ ]*:[ ]*@(\d+)( |\Z)/) {
7708 return $1;
7709 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007710 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007711 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007712}
7713
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007714sub isAnon($)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007715{ # "._N" or "$_N" in older GCC versions
7716 return ($_[0] and $_[0]=~/(\.|\$)\_\d+|anon\-/);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007717}
7718
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007719sub formatName($$)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007720{ # type name correction
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007721 if(defined $Cache{"formatName"}{$_[1]}{$_[0]}) {
7722 return $Cache{"formatName"}{$_[1]}{$_[0]};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007723 }
7724
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007725 my $N = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007726
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007727 if($_[1] ne "S")
7728 {
7729 $N=~s/\A[ ]+//g;
7730 $N=~s/[ ]+\Z//g;
7731 $N=~s/[ ]{2,}/ /g;
7732 }
7733
7734 $N=~s/[ ]*(\W)[ ]*/$1/g; # std::basic_string<char> const
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007735
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007736 $N=~s/\bvolatile const\b/const volatile/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007737
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007738 $N=~s/\b(long long|short|long) unsigned\b/unsigned $1/g;
7739 $N=~s/\b(short|long) int\b/$1/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007740
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007741 $N=~s/([\)\]])(const|volatile)\b/$1 $2/g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007742
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04007743 while($N=~s/>>/> >/g) {};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007744
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007745 if($_[1] eq "S")
7746 {
7747 if(index($N, "operator")!=-1) {
7748 $N=~s/\b(operator[ ]*)> >/$1>>/;
7749 }
7750 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007751
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04007752 return ($Cache{"formatName"}{$_[1]}{$_[0]} = $N);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007753}
7754
7755sub get_HeaderDeps($$)
7756{
7757 my ($AbsPath, $LibVersion) = @_;
7758 return () if(not $AbsPath or not $LibVersion);
7759 if(defined $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}) {
7760 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7761 }
7762 my %IncDir = ();
7763 detect_recursive_includes($AbsPath, $LibVersion);
7764 foreach my $HeaderPath (keys(%{$RecursiveIncludes{$LibVersion}{$AbsPath}}))
7765 {
7766 next if(not $HeaderPath);
7767 next if($MAIN_CPP_DIR and $HeaderPath=~/\A\Q$MAIN_CPP_DIR\E([\/\\]|\Z)/);
7768 my $Dir = get_dirname($HeaderPath);
7769 foreach my $Prefix (keys(%{$Header_Include_Prefix{$LibVersion}{$AbsPath}{$HeaderPath}}))
7770 {
7771 my $Dep = $Dir;
7772 if($Prefix)
7773 {
7774 if($OSgroup eq "windows")
7775 { # case insensitive seach on windows
7776 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//ig) {
7777 next;
7778 }
7779 }
7780 elsif($OSgroup eq "macos")
7781 { # seach in frameworks
7782 if(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7783 {
7784 if($HeaderPath=~/(.+\.framework)\/Headers\/([^\/]+)/)
7785 {# frameworks
7786 my ($HFramework, $HName) = ($1, $2);
7787 $Dep = $HFramework;
7788 }
7789 else
7790 {# mismatch
7791 next;
7792 }
7793 }
7794 }
7795 elsif(not $Dep=~s/[\/\\]+\Q$Prefix\E\Z//g)
7796 { # Linux, FreeBSD
7797 next;
7798 }
7799 }
7800 if(not $Dep)
7801 { # nothing to include
7802 next;
7803 }
7804 if(is_default_include_dir($Dep))
7805 { # included by the compiler
7806 next;
7807 }
7808 if(get_depth($Dep)==1)
7809 { # too short
7810 next;
7811 }
7812 if(isLibcDir($Dep))
7813 { # do NOT include /usr/include/{sys,bits}
7814 next;
7815 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007816 $IncDir{$Dep} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007817 }
7818 }
7819 $Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath} = sortIncPaths([keys(%IncDir)], $LibVersion);
7820 return @{$Cache{"get_HeaderDeps"}{$LibVersion}{$AbsPath}};
7821}
7822
7823sub sortIncPaths($$)
7824{
7825 my ($ArrRef, $LibVersion) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007826 if(not $ArrRef or $#{$ArrRef}<0) {
7827 return $ArrRef;
7828 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007829 @{$ArrRef} = sort {$b cmp $a} @{$ArrRef};
7830 @{$ArrRef} = sort {get_depth($a)<=>get_depth($b)} @{$ArrRef};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007831 @{$ArrRef} = sort {sortDeps($b, $a, $LibVersion)} @{$ArrRef};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007832 return $ArrRef;
7833}
7834
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04007835sub sortDeps($$$)
7836{
7837 if($Header_Dependency{$_[2]}{$_[0]}
7838 and not $Header_Dependency{$_[2]}{$_[1]}) {
7839 return 1;
7840 }
7841 elsif(not $Header_Dependency{$_[2]}{$_[0]}
7842 and $Header_Dependency{$_[2]}{$_[1]}) {
7843 return -1;
7844 }
7845 return 0;
7846}
7847
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007848sub join_P($$)
7849{
7850 my $S = "/";
7851 if($OSgroup eq "windows") {
7852 $S = "\\";
7853 }
7854 return join($S, @_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007855}
7856
7857sub get_namespace_additions($)
7858{
7859 my $NameSpaces = $_[0];
7860 my ($Additions, $AddNameSpaceId) = ("", 1);
7861 foreach my $NS (sort {$a=~/_/ <=> $b=~/_/} sort {lc($a) cmp lc($b)} keys(%{$NameSpaces}))
7862 {
7863 next if($SkipNameSpaces{$Version}{$NS});
7864 next if(not $NS or $NameSpaces->{$NS}==-1);
7865 next if($NS=~/(\A|::)iterator(::|\Z)/i);
7866 next if($NS=~/\A__/i);
7867 next if(($NS=~/\Astd::/ or $NS=~/\A(std|tr1|rel_ops|fcntl)\Z/) and not $STDCXX_TESTING);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007868 $NestedNameSpaces{$Version}{$NS} = 1; # for future use in reports
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007869 my ($TypeDecl_Prefix, $TypeDecl_Suffix) = ();
7870 my @NS_Parts = split(/::/, $NS);
7871 next if($#NS_Parts==-1);
7872 next if($NS_Parts[0]=~/\A(random|or)\Z/);
7873 foreach my $NS_Part (@NS_Parts)
7874 {
7875 $TypeDecl_Prefix .= "namespace $NS_Part\{";
7876 $TypeDecl_Suffix .= "}";
7877 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007878 my $TypeDecl = $TypeDecl_Prefix."typedef int tmp_add_type_".$AddNameSpaceId.";".$TypeDecl_Suffix;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007879 my $FuncDecl = "$NS\:\:tmp_add_type_$AddNameSpaceId tmp_add_func_$AddNameSpaceId(){return 0;};";
7880 $Additions.=" $TypeDecl\n $FuncDecl\n";
7881 $AddNameSpaceId+=1;
7882 }
7883 return $Additions;
7884}
7885
7886sub path_format($$)
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007887{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007888 my ($Path, $Fmt) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007889 $Path=~s/[\/\\]+\.?\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007890 if($Fmt eq "windows")
7891 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007892 $Path=~s/\//\\/g;
7893 $Path=lc($Path);
7894 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04007895 else
7896 { # forward slash to pass into MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007897 $Path=~s/\\/\//g;
7898 }
7899 return $Path;
7900}
7901
7902sub inc_opt($$)
7903{
7904 my ($Path, $Style) = @_;
7905 if($Style eq "GCC")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007906 { # GCC options
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007907 if($OSgroup eq "windows")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04007908 { # to MinGW GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007909 return "-I\"".path_format($Path, "unix")."\"";
7910 }
7911 elsif($OSgroup eq "macos"
7912 and $Path=~/\.framework\Z/)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04007913 { # to Apple's GCC
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007914 return "-F".esc(get_dirname($Path));
7915 }
7916 else {
7917 return "-I".esc($Path);
7918 }
7919 }
7920 elsif($Style eq "CL") {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04007921 return "/I \"".$Path."\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04007922 }
7923 return "";
7924}
7925
7926sub platformSpecs($)
7927{
7928 my $LibVersion = $_[0];
7929 my $Arch = getArch($LibVersion);
7930 if($OStarget eq "symbian")
7931 { # options for GCCE compiler
7932 my %Symbian_Opts = map {$_=>1} (
7933 "-D__GCCE__",
7934 "-DUNICODE",
7935 "-fexceptions",
7936 "-D__SYMBIAN32__",
7937 "-D__MARM_INTERWORK__",
7938 "-D_UNICODE",
7939 "-D__S60_50__",
7940 "-D__S60_3X__",
7941 "-D__SERIES60_3X__",
7942 "-D__EPOC32__",
7943 "-D__MARM__",
7944 "-D__EABI__",
7945 "-D__MARM_ARMV5__",
7946 "-D__SUPPORT_CPP_EXCEPTIONS__",
7947 "-march=armv5t",
7948 "-mapcs",
7949 "-mthumb-interwork",
7950 "-DEKA2",
7951 "-DSYMBIAN_ENABLE_SPLIT_HEADERS"
7952 );
7953 return join(" ", keys(%Symbian_Opts));
7954 }
7955 elsif($OSgroup eq "windows"
7956 and get_dumpmachine($GCC_PATH)=~/mingw/i)
7957 { # add options to MinGW compiler
7958 # to simulate the MSVC compiler
7959 my %MinGW_Opts = map {$_=>1} (
7960 "-D_WIN32",
7961 "-D_STDCALL_SUPPORTED",
7962 "-D__int64=\"long long\"",
7963 "-D__int32=int",
7964 "-D__int16=short",
7965 "-D__int8=char",
7966 "-D__possibly_notnullterminated=\" \"",
7967 "-D__nullterminated=\" \"",
7968 "-D__nullnullterminated=\" \"",
7969 "-D__w64=\" \"",
7970 "-D__ptr32=\" \"",
7971 "-D__ptr64=\" \"",
7972 "-D__forceinline=inline",
7973 "-D__inline=inline",
7974 "-D__uuidof(x)=IID()",
7975 "-D__try=",
7976 "-D__except(x)=",
7977 "-D__declspec(x)=__attribute__((x))",
7978 "-D__pragma(x)=",
7979 "-D_inline=inline",
7980 "-D__forceinline=__inline",
7981 "-D__stdcall=__attribute__((__stdcall__))",
7982 "-D__cdecl=__attribute__((__cdecl__))",
7983 "-D__fastcall=__attribute__((__fastcall__))",
7984 "-D__thiscall=__attribute__((__thiscall__))",
7985 "-D_stdcall=__attribute__((__stdcall__))",
7986 "-D_cdecl=__attribute__((__cdecl__))",
7987 "-D_fastcall=__attribute__((__fastcall__))",
7988 "-D_thiscall=__attribute__((__thiscall__))",
7989 "-DSHSTDAPI_(x)=x",
7990 "-D_MSC_EXTENSIONS",
7991 "-DSECURITY_WIN32",
7992 "-D_MSC_VER=1500",
7993 "-D_USE_DECLSPECS_FOR_SAL",
7994 "-D__noop=\" \"",
7995 "-DDECLSPEC_DEPRECATED=\" \"",
7996 "-D__builtin_alignof(x)=__alignof__(x)",
7997 "-DSORTPP_PASS");
7998 if($Arch eq "x86") {
7999 $MinGW_Opts{"-D_M_IX86=300"}=1;
8000 }
8001 elsif($Arch eq "x86_64") {
8002 $MinGW_Opts{"-D_M_AMD64=300"}=1;
8003 }
8004 elsif($Arch eq "ia64") {
8005 $MinGW_Opts{"-D_M_IA64=300"}=1;
8006 }
8007 return join(" ", keys(%MinGW_Opts));
8008 }
8009 return "";
8010}
8011
8012my %C_Structure = map {$_=>1} (
8013# FIXME: Can't separate union and struct data types before dumping,
8014# so it sometimes cause compilation errors for unknown reason
8015# when trying to declare TYPE* tmp_add_class_N
8016# This is a list of such structures + list of other C structures
8017 "sigval",
8018 "sigevent",
8019 "sigaction",
8020 "sigvec",
8021 "sigstack",
8022 "timeval",
8023 "timezone",
8024 "rusage",
8025 "rlimit",
8026 "wait",
8027 "flock",
8028 "stat",
8029 "_stat",
8030 "stat32",
8031 "_stat32",
8032 "stat64",
8033 "_stat64",
8034 "_stati64",
8035 "if_nameindex",
8036 "usb_device",
8037 "sigaltstack",
8038 "sysinfo",
8039 "timeLocale",
8040 "tcp_debug",
8041 "rpc_createerr",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008042 # Other
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008043 "timespec",
8044 "random_data",
8045 "drand48_data",
8046 "_IO_marker",
8047 "_IO_FILE",
8048 "lconv",
8049 "sched_param",
8050 "tm",
8051 "itimerspec",
8052 "_pthread_cleanup_buffer",
8053 "fd_set",
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008054 "siginfo",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008055 "mallinfo",
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008056 "timex",
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008057 "sigcontext",
8058 "ucontext",
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008059 # Mac
8060 "_timex",
8061 "_class_t",
8062 "_category_t",
8063 "_class_ro_t",
8064 "_protocol_t",
8065 "_message_ref_t",
8066 "_super_message_ref_t",
8067 "_ivar_t",
8068 "_ivar_list_t"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008069);
8070
8071sub getCompileCmd($$$)
8072{
8073 my ($Path, $Opt, $Inc) = @_;
8074 my $GccCall = $GCC_PATH;
8075 if($Opt) {
8076 $GccCall .= " ".$Opt;
8077 }
8078 $GccCall .= " -x ";
8079 if($OSgroup eq "macos") {
8080 $GccCall .= "objective-";
8081 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008082 if(check_gcc($GCC_PATH, "4"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008083 { # compile as "C++" header
8084 # to obtain complete dump using GCC 4.0
8085 $GccCall .= "c++-header";
8086 }
8087 else
8088 { # compile as "C++" source
8089 # GCC 3.3 cannot compile headers
8090 $GccCall .= "c++";
8091 }
8092 if(my $Opts = platformSpecs($Version))
8093 {# platform-specific options
8094 $GccCall .= " ".$Opts;
8095 }
8096 # allow extra qualifications
8097 # and other nonconformant code
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008098 $GccCall .= " -fpermissive";
8099 $GccCall .= " -w";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008100 if($NoStdInc)
8101 {
8102 $GccCall .= " -nostdinc";
8103 $GccCall .= " -nostdinc++";
8104 }
8105 if($CompilerOptions{$Version})
8106 { # user-defined options
8107 $GccCall .= " ".$CompilerOptions{$Version};
8108 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008109 $GccCall .= " \"$Path\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008110 if($Inc)
8111 { # include paths
8112 $GccCall .= " ".$Inc;
8113 }
8114 return $GccCall;
8115}
8116
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008117sub detectPreamble($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008118{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008119 my ($Content, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008120 my %HeaderElems = (
8121 # Types
8122 "stdio.h" => ["FILE", "va_list"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008123 "stddef.h" => ["NULL", "ptrdiff_t"],
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008124 "stdint.h" => ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
8125 "int8_t", "int16_t", "int32_t", "int64_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008126 "time.h" => ["time_t"],
8127 "sys/types.h" => ["ssize_t", "u_int32_t", "u_short", "u_char",
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008128 "u_int", "off_t", "u_quad_t", "u_long", "mode_t"],
8129 "unistd.h" => ["gid_t", "uid_t", "socklen_t"],
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008130 "stdbool.h" => ["_Bool"],
8131 "rpc/xdr.h" => ["bool_t"],
8132 "in_systm.h" => ["n_long", "n_short"],
8133 # Fields
Andrey Ponomarenkobede8372012-03-29 17:43:21 +04008134 "arpa/inet.h" => ["fw_src", "ip_src"],
8135 # Functions
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008136 "stdlib.h" => ["free", "malloc", "size_t"],
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008137 "string.h" => ["memmove", "strcmp"]
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008138 );
8139 my %AutoPreamble = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008140 foreach (keys(%HeaderElems))
8141 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008142 foreach my $Elem (@{$HeaderElems{$_}}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008143 $AutoPreamble{$Elem} = $_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008144 }
8145 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008146 my %Types = ();
8147 while($Content=~s/error\:\s*(field\s*|)\W+(.+?)\W+//)
8148 { # error: 'FILE' has not been declared
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008149 $Types{$2} = 1;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008150 }
8151 if(keys(%Types))
8152 {
8153 my %AddHeaders = ();
8154 foreach my $Type (keys(%Types))
8155 {
8156 if(my $Header = $AutoPreamble{$Type})
8157 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008158 if(my $Path = identifyHeader($Header, $LibVersion))
8159 {
8160 if(skipHeader($Path, $LibVersion)) {
8161 next;
8162 }
8163 $Path = path_format($Path, $OSgroup);
8164 $AddHeaders{$Path}{"Type"} = $Type;
8165 $AddHeaders{$Path}{"Header"} = $Header;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008166 }
8167 }
8168 }
8169 if(keys(%AddHeaders)) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008170 return \%AddHeaders;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008171 }
8172 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008173 return undef;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008174}
8175
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008176sub checkCTags($)
8177{
8178 my $Path = $_[0];
8179 if(not $Path) {
8180 return;
8181 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008182 my $CTags = undef;
8183
8184 if($OSgroup eq "bsd")
8185 { # use ectags on BSD
8186 $CTags = get_CmdPath("ectags");
8187 if(not $CTags) {
8188 printMsg("WARNING", "can't find \'ectags\' program");
8189 }
8190 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008191 if(not $CTags) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008192 $CTags = get_CmdPath("ctags");
8193 }
8194 if(not $CTags)
8195 {
8196 printMsg("WARNING", "can't find \'ctags\' program");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008197 return;
8198 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008199
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008200 if($OSgroup ne "linux")
8201 { # macos, freebsd, etc.
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008202 my $Info = `$CTags --version 2>\"$TMP_DIR/null\"`;
8203 if($Info!~/exuberant/i)
8204 {
8205 printMsg("WARNING", "incompatible version of \'ctags\' program");
8206 return;
8207 }
8208 }
8209
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008210 my $Out = $TMP_DIR."/ctags.txt";
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +04008211 system("$CTags --c-kinds=pxn -f \"$Out\" \"$Path\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008212 if($Debug) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008213 copy($Out, $DEBUG_PATH{$Version}."/ctags.txt");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008214 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008215 open(CTAGS, "<", $Out);
8216 while(my $Line = <CTAGS>)
8217 {
8218 chomp($Line);
8219 my ($Name, $Header, $Def, $Type, $Scpe) = split(/\t/, $Line);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008220 if(defined $Intrinsic_Keywords{$Name})
8221 { # noise
8222 next;
8223 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008224 if($Type eq "n")
8225 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008226 if(index($Scpe, "class:")==0) {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008227 next;
8228 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008229 if(index($Scpe, "struct:")==0) {
8230 next;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008231 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008232 if(index($Scpe, "namespace:")==0)
8233 {
8234 if($Scpe=~s/\Anamespace://) {
8235 $Name = $Scpe."::".$Name;
8236 }
8237 }
8238 $TUnit_NameSpaces{$Version}{$Name} = 1;
8239 }
8240 elsif($Type eq "p")
8241 {
8242 if(not $Scpe or index($Scpe, "namespace:")==0) {
8243 $TUnit_Funcs{$Version}{$Name} = 1;
8244 }
8245 }
8246 elsif($Type eq "x")
8247 {
8248 if(not $Scpe or index($Scpe, "namespace:")==0) {
8249 $TUnit_Vars{$Version}{$Name} = 1;
8250 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008251 }
8252 }
8253 close(CTAGS);
8254}
8255
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008256sub preChange($$)
8257{
8258 my ($HeaderPath, $IncStr) = @_;
8259
8260 my $PreprocessCmd = getCompileCmd($HeaderPath, "-E", $IncStr);
8261 my $Content = undef;
8262
8263 if($OStarget eq "windows"
8264 and get_dumpmachine($GCC_PATH)=~/mingw/i
8265 and $MinGWMode{$Version}!=-1)
8266 { # modify headers to compile by MinGW
8267 if(not $Content)
8268 { # preprocessing
8269 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8270 }
8271 if($Content=~s/__asm\s*(\{[^{}]*?\}|[^{};]*)//g)
8272 { # __asm { ... }
8273 $MinGWMode{$Version}=1;
8274 }
8275 if($Content=~s/\s+(\/ \/.*?)\n/\n/g)
8276 { # comments after preprocessing
8277 $MinGWMode{$Version}=1;
8278 }
8279 if($Content=~s/(\W)(0x[a-f]+|\d+)(i|ui)(8|16|32|64)(\W)/$1$2$5/g)
8280 { # 0xffui8
8281 $MinGWMode{$Version}=1;
8282 }
8283
8284 if($MinGWMode{$Version}) {
8285 printMsg("INFO", "Using MinGW compatibility mode");
8286 }
8287 }
8288
8289 if(($COMMON_LANGUAGE{$Version} eq "C" or $CheckHeadersOnly)
8290 and $CppMode{$Version}!=-1 and not $CppCompat and not $CPP_HEADERS)
8291 { # rename C++ keywords in C code
8292 # disable this code by -cpp-compatible option
8293 if(not $Content)
8294 { # preprocessing
8295 $Content = `$PreprocessCmd 2>\"$TMP_DIR/null\"`;
8296 }
8297 my $RegExp_C = join("|", keys(%CppKeywords_C));
8298 my $RegExp_F = join("|", keys(%CppKeywords_F));
8299 my $RegExp_O = join("|", keys(%CppKeywords_O));
8300
8301 my $Detected = undef;
8302
8303 while($Content=~s/(\A|\n[^\#\/\n][^\n]*?|\n)(\*\s*|\s+|\@|\,|\()($RegExp_C|$RegExp_F)(\s*(\,|\)|\;|\-\>|\.|\:\s*\d))/$1$2c99_$3$4/g)
8304 { # MATCH:
8305 # int foo(int new, int class, int (*new)(int));
8306 # unsigned private: 8;
8307 # DO NOT MATCH:
8308 # #pragma GCC visibility push(default)
8309 $CppMode{$Version} = 1;
8310 $Detected = "$1$2$3$4" if(not defined $Detected);
8311 }
8312 if($Content=~s/([^\w\s]|\w\s+)(?<!operator )(delete)(\s*\()/$1c99_$2$3/g)
8313 { # MATCH:
8314 # int delete(...);
8315 # int explicit(...);
8316 # DO NOT MATCH:
8317 # void operator delete(...)
8318 $CppMode{$Version} = 1;
8319 $Detected = "$1$2$3" if(not defined $Detected);
8320 }
8321 if($Content=~s/(\s+)($RegExp_O)(\s*(\;|\:))/$1c99_$2$3/g)
8322 { # MATCH:
8323 # int bool;
8324 # DO NOT MATCH:
8325 # bool X;
8326 # return *this;
8327 # throw;
8328 $CppMode{$Version} = 1;
8329 $Detected = "$1$2$3" if(not defined $Detected);
8330 }
8331 if($Content=~s/(\s+)(operator)(\s*(\(\s*\)\s*[^\(\s]|\(\s*[^\)\s]))/$1c99_$2$3/g)
8332 { # MATCH:
8333 # int operator(...);
8334 # DO NOT MATCH:
8335 # int operator()(...);
8336 $CppMode{$Version} = 1;
8337 $Detected = "$1$2$3" if(not defined $Detected);
8338 }
8339 if($Content=~s/([^\w\(\,\s]\s*|\s+)(operator)(\s*(\,\s*[^\(\s]|\)))/$1c99_$2$3/g)
8340 { # MATCH:
8341 # int foo(int operator);
8342 # int foo(int operator, int other);
8343 # DO NOT MATCH:
8344 # int operator,(...);
8345 $CppMode{$Version} = 1;
8346 $Detected = "$1$2$3" if(not defined $Detected);
8347 }
8348 if($Content=~s/(\*\s*|\w\s+)(bool)(\s*(\,|\)))/$1c99_$2$3/g)
8349 { # MATCH:
8350 # int foo(gboolean *bool);
8351 # DO NOT MATCH:
8352 # void setTabEnabled(int index, bool);
8353 $CppMode{$Version} = 1;
8354 $Detected = "$1$2$3" if(not defined $Detected);
8355 }
8356 if($Content=~s/(\w)(\s*[^\w\(\,\s]\s*|\s+)(this|throw)(\s*[\,\)])/$1$2c99_$3$4/g)
8357 { # MATCH:
8358 # int foo(int* this);
8359 # int bar(int this);
8360 # int baz(int throw);
8361 # DO NOT MATCH:
8362 # foo(X, this);
8363 $CppMode{$Version} = 1;
8364 $Detected = "$1$2$3$4" if(not defined $Detected);
8365 }
8366 if($Content=~s/(struct |extern )(template) /$1c99_$2 /g)
8367 { # MATCH:
8368 # struct template {...};
8369 # extern template foo(...);
8370 $CppMode{$Version} = 1;
8371 $Detected = "$1$2" if(not defined $Detected);
8372 }
8373
8374 if($CppMode{$Version} == 1)
8375 {
8376 if($Debug)
8377 {
8378 $Detected=~s/\A\s+//g;
8379 printMsg("INFO", "Detected code: \"$Detected\"");
8380 }
8381 }
8382
8383 # remove typedef enum NAME NAME;
8384 my @FwdTypedefs = $Content=~/typedef\s+enum\s+(\w+)\s+(\w+);/g;
8385 my $N = 0;
8386 while($N<=$#FwdTypedefs-1)
8387 {
8388 my $S = $FwdTypedefs[$N];
8389 if($S eq $FwdTypedefs[$N+1])
8390 {
8391 $Content=~s/typedef\s+enum\s+\Q$S\E\s+\Q$S\E;//g;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008392 $CppMode{$Version} = 1;
8393
8394 if($Debug) {
8395 printMsg("INFO", "Detected code: \"typedef enum $S $S;\"");
8396 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008397 }
8398 $N+=2;
8399 }
8400
8401 if($CppMode{$Version}==1) {
8402 printMsg("INFO", "Using C++ compatibility mode");
8403 }
8404 }
8405
8406 if($CppMode{$Version}==1
8407 or $MinGWMode{$Version}==1)
8408 {
8409 my $IPath = $TMP_DIR."/dump$Version.i";
8410 writeFile($IPath, $Content);
8411 return $IPath;
8412 }
8413
8414 return undef;
8415}
8416
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008417sub getDump()
8418{
8419 if(not $GCC_PATH) {
8420 exitStatus("Error", "internal error - GCC path is not set");
8421 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008422
8423 my @Headers = keys(%{$Registered_Headers{$Version}});
8424 @Headers = sort {int($Registered_Headers{$Version}{$a}{"Pos"})<=>int($Registered_Headers{$Version}{$b}{"Pos"})} @Headers;
8425
8426 my $IncludeString = getIncString(getIncPaths(@{$Include_Preamble{$Version}}, @Headers), "GCC");
8427
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008428 my $TmpHeaderPath = $TMP_DIR."/dump".$Version.".h";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008429 my $HeaderPath = $TmpHeaderPath;
8430
8431 # write tmp-header
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008432 open(TMP_HEADER, ">", $TmpHeaderPath) || die ("can't open file \'$TmpHeaderPath\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008433 if(my $AddDefines = $Descriptor{$Version}{"Defines"})
8434 {
8435 $AddDefines=~s/\n\s+/\n /g;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008436 print TMP_HEADER "\n // add defines\n ".$AddDefines."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008437 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008438 print TMP_HEADER "\n // add includes\n";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008439 foreach my $HPath (@{$Include_Preamble{$Version}}) {
8440 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008441 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008442 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008443 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008444 if(not grep {$HPath eq $_} (@{$Include_Preamble{$Version}})) {
8445 print TMP_HEADER " #include \"".path_format($HPath, "unix")."\"\n";
8446 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008447 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008448 close(TMP_HEADER);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008449
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008450 if($ExtraInfo)
8451 { # extra information for other tools
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008452 if($IncludeString) {
8453 writeFile($ExtraInfo."/include-string", $IncludeString);
8454 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008455 writeFile($ExtraInfo."/recursive-includes", Dumper($RecursiveIncludes{$Version}));
8456 writeFile($ExtraInfo."/direct-includes", Dumper($Header_Includes{$Version}));
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008457
8458 if(my @Redirects = keys(%{$Header_ErrorRedirect{$Version}}))
8459 {
8460 my $REDIR = "";
8461 foreach my $P1 (sort @Redirects) {
8462 $REDIR .= $P1.";".$Header_ErrorRedirect{$Version}{$P1}."\n";
8463 }
8464 writeFile($ExtraInfo."/include-redirect", $REDIR);
8465 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008466 }
8467
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008468 if(not keys(%{$TargetHeaders{$Version}}))
8469 { # Target headers
8470 addTargetHeaders($Version);
8471 }
8472
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008473 # clean memory
8474 %RecursiveIncludes = ();
8475 %Header_Include_Prefix = ();
8476 %Header_Includes = ();
8477
8478 # clean cache
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008479 delete($Cache{"identifyHeader"});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008480 delete($Cache{"detect_header_includes"});
8481 delete($Cache{"selectSystemHeader"});
8482
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008483 # preprocessing stage
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008484 my $Pre = callPreprocessor($TmpHeaderPath, $IncludeString, $Version);
8485 checkPreprocessedUnit($Pre);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008486
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008487 if($ExtraInfo)
8488 { # extra information for other tools
8489 writeFile($ExtraInfo."/header-paths", join("\n", sort keys(%{$PreprocessedHeaders{$Version}})));
8490 }
8491
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008492 # clean memory
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008493 delete($Include_Neighbors{$Version});
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008494 delete($PreprocessedHeaders{$Version});
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008495
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008496 if($COMMON_LANGUAGE{$Version} eq "C++") {
8497 checkCTags($Pre);
8498 }
8499
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008500 if(my $PrePath = preChange($TmpHeaderPath, $IncludeString))
8501 { # try to correct the preprocessor output
8502 $HeaderPath = $PrePath;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008503 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04008504
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008505 if($COMMON_LANGUAGE{$Version} eq "C++")
8506 { # add classes and namespaces to the dump
8507 my $CHdump = "-fdump-class-hierarchy -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008508 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008509 or $MinGWMode{$Version}==1) {
8510 $CHdump .= " -fpreprocessed";
8511 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008512 my $ClassHierarchyCmd = getCompileCmd($HeaderPath, $CHdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008513 chdir($TMP_DIR);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04008514 system($ClassHierarchyCmd." >null 2>&1");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008515 chdir($ORIG_DIR);
8516 if(my $ClassDump = (cmd_find($TMP_DIR,"f","*.class",1))[0])
8517 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008518 my $Content = readFile($ClassDump);
8519 foreach my $ClassInfo (split(/\n\n/, $Content))
8520 {
8521 if($ClassInfo=~/\AClass\s+(.+)\s*/i)
8522 {
8523 my $CName = $1;
8524 next if($CName=~/\A(__|_objc_|_opaque_)/);
8525 $TUnit_NameSpaces{$Version}{$CName} = -1;
8526 if($CName=~/\A[\w:]+\Z/)
8527 { # classes
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008528 $TUnit_Classes{$Version}{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008529 }
8530 if($CName=~/(\w[\w:]*)::/)
8531 { # namespaces
8532 my $NS = $1;
8533 if(not defined $TUnit_NameSpaces{$Version}{$NS}) {
8534 $TUnit_NameSpaces{$Version}{$NS} = 1;
8535 }
8536 }
8537 }
8538 elsif($ClassInfo=~/\AVtable\s+for\s+(.+)\n((.|\n)+)\Z/i)
8539 { # read v-tables (advanced approach)
8540 my ($CName, $VTable) = ($1, $2);
8541 $ClassVTable_Content{$Version}{$CName} = $VTable;
8542 }
8543 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008544 foreach my $NS (keys(%{$AddNameSpaces{$Version}}))
8545 { # add user-defined namespaces
8546 $TUnit_NameSpaces{$Version}{$NS} = 1;
8547 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008548 if($Debug)
8549 { # debug mode
8550 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04008551 copy($ClassDump, $DEBUG_PATH{$Version}."/class-hierarchy-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008552 }
8553 unlink($ClassDump);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008554 }
8555
8556 # add namespaces and classes
8557 if(my $NS_Add = get_namespace_additions($TUnit_NameSpaces{$Version}))
8558 { # GCC on all supported platforms does not include namespaces to the dump by default
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008559 appendFile($HeaderPath, "\n // add namespaces\n".$NS_Add);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008560 }
8561 # some GCC versions don't include class methods to the TU dump by default
8562 my ($AddClass, $ClassNum) = ("", 0);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008563 my $GCC_44 = check_gcc($GCC_PATH, "4.4"); # support for old GCC versions
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008564 foreach my $CName (sort keys(%{$TUnit_Classes{$Version}}))
8565 {
8566 next if($C_Structure{$CName});
8567 next if(not $STDCXX_TESTING and $CName=~/\Astd::/);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008568 next if($SkipTypes{$Version}{$CName});
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008569 if(not $Force and $GCC_44
8570 and $OSgroup eq "linux")
8571 { # optimization for linux with GCC >= 4.4
8572 # disable this code by -force option
8573 if(index($CName, "::")!=-1)
8574 { # should be added by name space
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +04008575 next;
8576 }
8577 }
8578 else
8579 {
8580 if($CName=~/\A(.+)::[^:]+\Z/
8581 and $TUnit_Classes{$Version}{$1})
8582 { # classes inside other classes
8583 next;
8584 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008585 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008586 if(defined $TUnit_Funcs{$Version}{$CName})
8587 { # the same name for a function and type
8588 next;
8589 }
8590 if(defined $TUnit_Vars{$Version}{$CName})
8591 { # the same name for a variable and type
8592 next;
8593 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008594 $AddClass .= " $CName* tmp_add_class_".($ClassNum++).";\n";
8595 }
8596 if($AddClass) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008597 appendFile($HeaderPath, "\n // add classes\n".$AddClass);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008598 }
8599 }
8600 writeLog($Version, "Temporary header file \'$TmpHeaderPath\' with the following content will be compiled to create GCC translation unit dump:\n".readFile($TmpHeaderPath)."\n");
8601 # create TU dump
8602 my $TUdump = "-fdump-translation-unit -fkeep-inline-functions -c";
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008603 if($CppMode{$Version}==1
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008604 or $MinGWMode{$Version}==1) {
8605 $TUdump .= " -fpreprocessed";
8606 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008607 my $SyntaxTreeCmd = getCompileCmd($HeaderPath, $TUdump, $IncludeString);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008608 writeLog($Version, "The GCC parameters:\n $SyntaxTreeCmd\n\n");
8609 chdir($TMP_DIR);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008610 system($SyntaxTreeCmd." >\"$TMP_DIR/tu_errors\" 2>&1");
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008611 my $Errors = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008612 if($?)
8613 { # failed to compile, but the TU dump still can be created
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008614 if($Errors = readFile($TMP_DIR."/tu_errors"))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008615 { # try to recompile
8616 # FIXME: handle other errors and try to recompile
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008617 if($CppMode{$Version}==1
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008618 and index($Errors, "c99_")!=-1)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008619 { # disable c99 mode and try again
Andrey Ponomarenko07aea072012-11-12 16:15:07 +04008620 $CppMode{$Version}=-1;
8621 printMsg("INFO", "Disabling C++ compatibility mode");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008622 resetLogging($Version);
8623 $TMP_DIR = tempdir(CLEANUP=>1);
8624 return getDump();
8625 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008626 elsif($AutoPreambleMode{$Version}!=-1
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008627 and my $AddHeaders = detectPreamble($Errors, $Version))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008628 { # add auto preamble headers and try again
8629 $AutoPreambleMode{$Version}=-1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008630 my @Headers = sort {$b cmp $a} keys(%{$AddHeaders}); # sys/types.h should be the first
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008631 foreach my $Num (0 .. $#Headers)
8632 {
8633 my $Path = $Headers[$Num];
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008634 if(not grep {$Path eq $_} (@{$Include_Preamble{$Version}}))
8635 {
8636 push_U($Include_Preamble{$Version}, $Path);
8637 printMsg("INFO", "Add \'".$AddHeaders->{$Path}{"Header"}."\' preamble header for \'".$AddHeaders->{$Path}{"Type"}."\'");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008638 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008639 }
8640 resetLogging($Version);
8641 $TMP_DIR = tempdir(CLEANUP=>1);
8642 return getDump();
8643 }
8644 elsif($Cpp0xMode{$Version}!=-1
8645 and ($Errors=~/\Q-std=c++0x\E/
8646 or $Errors=~/is not a class or namespace/))
8647 { # c++0x: enum class
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008648 if(check_gcc($GCC_PATH, "4.6"))
8649 {
8650 $Cpp0xMode{$Version}=-1;
8651 printMsg("INFO", "Enabling c++0x mode");
8652 resetLogging($Version);
8653 $TMP_DIR = tempdir(CLEANUP=>1);
8654 $CompilerOptions{$Version} .= " -std=c++0x";
8655 return getDump();
8656 }
8657 else {
8658 printMsg("WARNING", "Probably c++0x construction detected");
8659 }
8660
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008661 }
8662 elsif($MinGWMode{$Version}==1)
8663 { # disable MinGW mode and try again
8664 $MinGWMode{$Version}=-1;
8665 resetLogging($Version);
8666 $TMP_DIR = tempdir(CLEANUP=>1);
8667 return getDump();
8668 }
8669 writeLog($Version, $Errors);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008670 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04008671 else {
8672 writeLog($Version, "$!: $?\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008673 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008674 printMsg("ERROR", "some errors occurred when compiling headers");
8675 printErrorLog($Version);
8676 $COMPILE_ERRORS = $ERROR_CODE{"Compile_Error"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008677 writeLog($Version, "\n"); # new line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008678 }
8679 chdir($ORIG_DIR);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008680 unlink($TmpHeaderPath);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008681 unlink($HeaderPath);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008682
8683 if(my @TUs = cmd_find($TMP_DIR,"f","*.tu",1)) {
8684 return $TUs[0];
8685 }
8686 else
8687 {
8688 my $Msg = "can't compile header(s)";
8689 if($Errors=~/error trying to exec \W+cc1plus\W+/) {
8690 $Msg .= "\nDid you install G++?";
8691 }
8692 exitStatus("Cannot_Compile", $Msg);
8693 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008694}
8695
8696sub cmd_file($)
8697{
8698 my $Path = $_[0];
8699 return "" if(not $Path or not -e $Path);
8700 if(my $CmdPath = get_CmdPath("file")) {
8701 return `$CmdPath -b \"$Path\"`;
8702 }
8703 return "";
8704}
8705
8706sub getIncString($$)
8707{
8708 my ($ArrRef, $Style) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04008709 return "" if(not $ArrRef or $#{$ArrRef}<0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008710 my $String = "";
8711 foreach (@{$ArrRef}) {
8712 $String .= " ".inc_opt($_, $Style);
8713 }
8714 return $String;
8715}
8716
8717sub getIncPaths(@)
8718{
8719 my @HeaderPaths = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008720 my @IncPaths = @{$Add_Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008721 if($INC_PATH_AUTODETECT{$Version})
8722 { # auto-detecting dependencies
8723 my %Includes = ();
8724 foreach my $HPath (@HeaderPaths)
8725 {
8726 foreach my $Dir (get_HeaderDeps($HPath, $Version))
8727 {
8728 if($Skip_Include_Paths{$Version}{$Dir}) {
8729 next;
8730 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008731 if($SystemRoot)
8732 {
8733 if($Skip_Include_Paths{$Version}{$SystemRoot.$Dir}) {
8734 next;
8735 }
8736 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008737 $Includes{$Dir} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008738 }
8739 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008740 foreach my $Dir (@{sortIncPaths([keys(%Includes)], $Version)}) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008741 push_U(\@IncPaths, $Dir);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008742 }
8743 }
8744 else
8745 { # user-defined paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008746 @IncPaths = @{$Include_Paths{$Version}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008747 }
8748 return \@IncPaths;
8749}
8750
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008751sub push_U($@)
8752{ # push unique
8753 if(my $Array = shift @_)
8754 {
8755 if(@_)
8756 {
8757 my %Exist = map {$_=>1} @{$Array};
8758 foreach my $Elem (@_)
8759 {
8760 if(not defined $Exist{$Elem})
8761 {
8762 push(@{$Array}, $Elem);
8763 $Exist{$Elem} = 1;
8764 }
8765 }
8766 }
8767 }
8768}
8769
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008770sub callPreprocessor($$$)
8771{
8772 my ($Path, $Inc, $LibVersion) = @_;
8773 return "" if(not $Path or not -f $Path);
8774 my $IncludeString=$Inc;
8775 if(not $Inc) {
8776 $IncludeString = getIncString(getIncPaths($Path), "GCC");
8777 }
8778 my $Cmd = getCompileCmd($Path, "-dD -E", $IncludeString);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04008779 my $Out = $TMP_DIR."/preprocessed.h";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008780 system($Cmd." >\"$Out\" 2>\"$TMP_DIR/null\"");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04008781 return $Out;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008782}
8783
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008784sub cmd_find($;$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008785{ # native "find" is much faster than File::Find (~6x)
8786 # also the File::Find doesn't support --maxdepth N option
8787 # so using the cross-platform wrapper for the native one
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008788 my ($Path, $Type, $Name, $MaxDepth, $UseRegex) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008789 return () if(not $Path or not -e $Path);
8790 if($OSgroup eq "windows")
8791 {
8792 my $DirCmd = get_CmdPath("dir");
8793 if(not $DirCmd) {
8794 exitStatus("Not_Found", "can't find \"dir\" command");
8795 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008796 $Path = get_abs_path($Path);
8797 $Path = path_format($Path, $OSgroup);
8798 my $Cmd = $DirCmd." \"$Path\" /B /O";
8799 if($MaxDepth!=1) {
8800 $Cmd .= " /S";
8801 }
8802 if($Type eq "d") {
8803 $Cmd .= " /AD";
8804 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008805 elsif($Type eq "f") {
8806 $Cmd .= " /A-D";
8807 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008808 my @Files = split(/\n/, `$Cmd 2>\"$TMP_DIR/null\"`);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008809 if($Name)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008810 {
8811 if(not $UseRegex)
8812 { # FIXME: how to search file names in MS shell?
8813 # wildcard to regexp
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008814 $Name=~s/\*/.*/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008815 $Name='\A'.$Name.'\Z';
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008816 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008817 @Files = grep { /$Name/i } @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008818 }
8819 my @AbsPaths = ();
8820 foreach my $File (@Files)
8821 {
8822 if(not is_abs($File)) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008823 $File = join_P($Path, $File);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008824 }
8825 if($Type eq "f" and not -f $File)
8826 { # skip dirs
8827 next;
8828 }
8829 push(@AbsPaths, path_format($File, $OSgroup));
8830 }
8831 if($Type eq "d") {
8832 push(@AbsPaths, $Path);
8833 }
8834 return @AbsPaths;
8835 }
8836 else
8837 {
8838 my $FindCmd = get_CmdPath("find");
8839 if(not $FindCmd) {
8840 exitStatus("Not_Found", "can't find a \"find\" command");
8841 }
8842 $Path = get_abs_path($Path);
8843 if(-d $Path and -l $Path
8844 and $Path!~/\/\Z/)
8845 { # for directories that are symlinks
8846 $Path.="/";
8847 }
8848 my $Cmd = $FindCmd." \"$Path\"";
8849 if($MaxDepth) {
8850 $Cmd .= " -maxdepth $MaxDepth";
8851 }
8852 if($Type) {
8853 $Cmd .= " -type $Type";
8854 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008855 if($Name and not $UseRegex)
8856 { # wildcards
8857 $Cmd .= " -name \"$Name\"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008858 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008859 my $Res = `$Cmd 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008860 if($? and $!) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04008861 printMsg("ERROR", "problem with \'find\' utility ($?): $!");
8862 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008863 my @Files = split(/\n/, $Res);
8864 if($Name and $UseRegex)
8865 { # regex
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04008866 @Files = grep { /$Name/ } @Files;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04008867 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +04008868 return @Files;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008869 }
8870}
8871
8872sub unpackDump($)
8873{
8874 my $Path = $_[0];
8875 return "" if(not $Path or not -e $Path);
8876 $Path = get_abs_path($Path);
8877 $Path = path_format($Path, $OSgroup);
8878 my ($Dir, $FileName) = separate_path($Path);
8879 my $UnpackDir = $TMP_DIR."/unpack";
8880 rmtree($UnpackDir);
8881 mkpath($UnpackDir);
8882 if($FileName=~s/\Q.zip\E\Z//g)
8883 { # *.zip
8884 my $UnzipCmd = get_CmdPath("unzip");
8885 if(not $UnzipCmd) {
8886 exitStatus("Not_Found", "can't find \"unzip\" command");
8887 }
8888 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008889 system("$UnzipCmd \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008890 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008891 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008892 }
8893 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008894 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008895 if(not @Contents) {
8896 exitStatus("Error", "can't extract \'$Path\'");
8897 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008898 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008899 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04008900 elsif($FileName=~s/\Q.tar.gz\E(\.\w+|)\Z//g)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008901 { # *.tar.gz
8902 if($OSgroup eq "windows")
8903 { # -xvzf option is not implemented in tar.exe (2003)
8904 # use "gzip.exe -k -d -f" + "tar.exe -xvf" instead
8905 my $TarCmd = get_CmdPath("tar");
8906 if(not $TarCmd) {
8907 exitStatus("Not_Found", "can't find \"tar\" command");
8908 }
8909 my $GzipCmd = get_CmdPath("gzip");
8910 if(not $GzipCmd) {
8911 exitStatus("Not_Found", "can't find \"gzip\" command");
8912 }
8913 chdir($UnpackDir);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008914 system("$GzipCmd -k -d -f \"$Path\""); # keep input files (-k)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008915 if($?) {
8916 exitStatus("Error", "can't extract \'$Path\'");
8917 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008918 system("$TarCmd -xvf \"$Dir\\$FileName.tar\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008919 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008920 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008921 }
8922 chdir($ORIG_DIR);
8923 unlink($Dir."/".$FileName.".tar");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008924 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008925 if(not @Contents) {
8926 exitStatus("Error", "can't extract \'$Path\'");
8927 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008928 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008929 }
8930 else
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008931 { # Unix, Mac
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008932 my $TarCmd = get_CmdPath("tar");
8933 if(not $TarCmd) {
8934 exitStatus("Not_Found", "can't find \"tar\" command");
8935 }
8936 chdir($UnpackDir);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008937 system("$TarCmd -xvzf \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008938 if($?) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008939 exitStatus("Error", "can't extract \'$Path\' ($?): $!");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008940 }
8941 chdir($ORIG_DIR);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008942 my @Contents = cmd_find($UnpackDir, "f");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008943 if(not @Contents) {
8944 exitStatus("Error", "can't extract \'$Path\'");
8945 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04008946 return $Contents[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008947 }
8948 }
8949}
8950
8951sub createArchive($$)
8952{
8953 my ($Path, $To) = @_;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04008954 if(not $To) {
8955 $To = ".";
8956 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008957 if(not $Path or not -e $Path
8958 or not -d $To) {
8959 return "";
8960 }
8961 my ($From, $Name) = separate_path($Path);
8962 if($OSgroup eq "windows")
8963 { # *.zip
8964 my $ZipCmd = get_CmdPath("zip");
8965 if(not $ZipCmd) {
8966 exitStatus("Not_Found", "can't find \"zip\"");
8967 }
8968 my $Pkg = $To."/".$Name.".zip";
8969 unlink($Pkg);
8970 chdir($To);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +04008971 system("$ZipCmd -j \"$Name.zip\" \"$Path\" >\"$TMP_DIR/null\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04008972 if($?)
8973 { # cannot allocate memory (or other problems with "zip")
8974 unlink($Path);
8975 exitStatus("Error", "can't pack the ABI dump: ".$!);
8976 }
8977 chdir($ORIG_DIR);
8978 unlink($Path);
8979 return $Pkg;
8980 }
8981 else
8982 { # *.tar.gz
8983 my $TarCmd = get_CmdPath("tar");
8984 if(not $TarCmd) {
8985 exitStatus("Not_Found", "can't find \"tar\"");
8986 }
8987 my $GzipCmd = get_CmdPath("gzip");
8988 if(not $GzipCmd) {
8989 exitStatus("Not_Found", "can't find \"gzip\"");
8990 }
8991 my $Pkg = abs_path($To)."/".$Name.".tar.gz";
8992 unlink($Pkg);
8993 chdir($From);
8994 system($TarCmd, "-czf", $Pkg, $Name);
8995 if($?)
8996 { # cannot allocate memory (or other problems with "tar")
8997 unlink($Path);
8998 exitStatus("Error", "can't pack the ABI dump: ".$!);
8999 }
9000 chdir($ORIG_DIR);
9001 unlink($Path);
9002 return $To."/".$Name.".tar.gz";
9003 }
9004}
9005
9006sub is_header_file($)
9007{
9008 if($_[0]=~/\.($HEADER_EXT)\Z/i) {
9009 return $_[0];
9010 }
9011 return 0;
9012}
9013
9014sub is_not_header($)
9015{
9016 if($_[0]=~/\.\w+\Z/
9017 and $_[0]!~/\.($HEADER_EXT)\Z/i) {
9018 return 1;
9019 }
9020 return 0;
9021}
9022
9023sub is_header($$$)
9024{
9025 my ($Header, $UserDefined, $LibVersion) = @_;
9026 return 0 if(-d $Header);
9027 if(-f $Header) {
9028 $Header = get_abs_path($Header);
9029 }
9030 else
9031 {
9032 if(is_abs($Header))
9033 { # incorrect absolute path
9034 return 0;
9035 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009036 if(my $HPath = identifyHeader($Header, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009037 $Header = $HPath;
9038 }
9039 else
9040 { # can't find header
9041 return 0;
9042 }
9043 }
9044 if($Header=~/\.\w+\Z/)
9045 { # have an extension
9046 return is_header_file($Header);
9047 }
9048 else
9049 {
9050 if($UserDefined==2)
9051 { # specified on the command line
9052 if(cmd_file($Header)!~/HTML|XML/i) {
9053 return $Header;
9054 }
9055 }
9056 elsif($UserDefined)
9057 { # specified in the XML-descriptor
9058 # header file without an extension
9059 return $Header;
9060 }
9061 else
9062 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +04009063 if(index($Header, "/include/")!=-1
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009064 or cmd_file($Header)=~/C[\+]*\s+program/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009065 { # !~/HTML|XML|shared|dynamic/i
9066 return $Header;
9067 }
9068 }
9069 }
9070 return 0;
9071}
9072
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009073sub addTargetHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009074{
9075 my $LibVersion = $_[0];
9076 foreach my $RegHeader (keys(%{$Registered_Headers{$LibVersion}}))
9077 {
9078 my $RegDir = get_dirname($RegHeader);
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009079 $TargetHeaders{$LibVersion}{get_filename($RegHeader)} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009080
9081 if(not $INC_PATH_AUTODETECT{$LibVersion}) {
9082 detect_recursive_includes($RegHeader, $LibVersion);
9083 }
9084
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009085 foreach my $RecInc (keys(%{$RecursiveIncludes{$LibVersion}{$RegHeader}}))
9086 {
9087 my $Dir = get_dirname($RecInc);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009088
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009089 if(familiarDirs($RegDir, $Dir)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009090 or $RecursiveIncludes{$LibVersion}{$RegHeader}{$RecInc}!=1)
9091 { # in the same directory or included by #include "..."
Andrey Ponomarenko46bef512013-06-14 16:33:03 +04009092 $TargetHeaders{$LibVersion}{get_filename($RecInc)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009093 }
9094 }
9095 }
9096}
9097
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009098sub familiarDirs($$)
9099{
9100 my ($D1, $D2) = @_;
9101 if($D1 eq $D2) {
9102 return 1;
9103 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009104
9105 my $U1 = index($D1, "/usr/");
9106 my $U2 = index($D2, "/usr/");
9107
9108 if($U1==0 and $U2!=0) {
9109 return 0;
9110 }
9111
9112 if($U2==0 and $U1!=0) {
9113 return 0;
9114 }
9115
9116 if(index($D2, $D1."/")==0) {
9117 return 1;
9118 }
9119
9120 # /usr/include/DIR
9121 # /home/user/DIR
9122
9123 my $DL = get_depth($D1);
9124
9125 my @Dirs1 = ($D1);
9126 while($DL - get_depth($D1)<=2
9127 and get_depth($D1)>=4
9128 and $D1=~s/[\/\\]+[^\/\\]*?\Z//) {
9129 push(@Dirs1, $D1);
9130 }
9131
9132 my @Dirs2 = ($D2);
9133 while(get_depth($D2)>=4
9134 and $D2=~s/[\/\\]+[^\/\\]*?\Z//) {
9135 push(@Dirs2, $D2);
9136 }
9137
9138 foreach my $P1 (@Dirs1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009139 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009140 foreach my $P2 (@Dirs2)
9141 {
9142
9143 if($P1 eq $P2) {
9144 return 1;
9145 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009146 }
9147 }
9148 return 0;
9149}
9150
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009151sub readHeaders($)
9152{
9153 $Version = $_[0];
9154 printMsg("INFO", "checking header(s) ".$Descriptor{$Version}{"Version"}." ...");
9155 my $DumpPath = getDump();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009156 if($Debug)
9157 { # debug mode
9158 mkpath($DEBUG_PATH{$Version});
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009159 copy($DumpPath, $DEBUG_PATH{$Version}."/translation-unit-dump.txt");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009160 }
9161 getInfo($DumpPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009162}
9163
9164sub prepareTypes($)
9165{
9166 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009167 if(not checkDump($LibVersion, "2.0"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009168 { # support for old ABI dumps
9169 # type names have been corrected in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009170 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009171 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009172 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
9173 if($TName=~/\A(\w+)::(\w+)/) {
9174 my ($P1, $P2) = ($1, $2);
9175 if($P1 eq $P2) {
9176 $TName=~s/\A$P1:\:$P1(\W)/$P1$1/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009177 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009178 else {
9179 $TName=~s/\A(\w+:\:)$P2:\:$P2(\W)/$1$P2$2/;
9180 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009181 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009182 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = $TName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009183 }
9184 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009185 if(not checkDump($LibVersion, "2.5"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009186 { # support for old ABI dumps
9187 # V < 2.5: array size == "number of elements"
9188 # V >= 2.5: array size in bytes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009189 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009190 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009191 my %Type = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009192 if($Type{"Type"} eq "Array")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009193 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009194 if(my $Size = $Type{"Size"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009195 { # array[N]
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009196 my %Base = get_OneStep_BaseType($Type{"Tid"}, $TypeInfo{$LibVersion});
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009197 $Size *= $Base{"Size"};
9198 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = "$Size";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009199 }
9200 else
9201 { # array[] is a pointer
9202 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $WORD_SIZE{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009203 }
9204 }
9205 }
9206 }
9207 my $V2 = ($LibVersion==1)?2:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009208 if(not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009209 { # support for old ABI dumps
9210 # size of "method ptr" corrected in 2.7
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009211 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009212 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +04009213 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009214 if($PureType{"Type"} eq "MethodPtr")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009215 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009216 my %Type = get_Type($TypeId, $LibVersion);
9217 my $TypeId_2 = getTypeIdByName($PureType{"Name"}, $V2);
9218 my %Type2 = get_Type($TypeId_2, $V2);
9219 if($Type{"Size"} ne $Type2{"Size"}) {
9220 $TypeInfo{$LibVersion}{$TypeId}{"Size"} = $Type2{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009221 }
9222 }
9223 }
9224 }
9225}
9226
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009227sub prepareSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009228{
9229 my $LibVersion = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009230
9231 if(not keys(%{$SymbolInfo{$LibVersion}}))
9232 { # check if input is valid
9233 if(not $ExtendedCheck and not $CheckObjectsOnly)
9234 {
9235 if($CheckHeadersOnly) {
9236 exitStatus("Empty_Set", "the set of public symbols is empty (".$Descriptor{$LibVersion}{"Version"}.")");
9237 }
9238 else {
9239 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection (".$Descriptor{$LibVersion}{"Version"}.")");
9240 }
9241 }
9242 }
9243
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009244 my $Remangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009245 if(not checkDump(1, "2.10")
9246 or not checkDump(2, "2.10"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009247 { # different formats
9248 $Remangle = 1;
9249 }
9250 if($CheckHeadersOnly)
9251 { # different languages
9252 if($UserLang)
9253 { # --lang=LANG for both versions
9254 if(($UsedDump{1}{"V"} and $UserLang ne $UsedDump{1}{"L"})
9255 or ($UsedDump{2}{"V"} and $UserLang ne $UsedDump{2}{"L"}))
9256 {
9257 if($UserLang eq "C++")
9258 { # remangle symbols
9259 $Remangle = 1;
9260 }
9261 elsif($UserLang eq "C")
9262 { # remove mangling
9263 $Remangle = -1;
9264 }
9265 }
9266 }
9267 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009268
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009269 foreach my $InfoId (sort {int($b)<=>int($a)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009270 { # reverse order: D0, D1, D2, D0 (artificial, GCC < 4.5), C1, C2
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009271 if(not checkDump($LibVersion, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009272 { # support for old ABI dumps
9273 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
9274 {
9275 foreach my $P (keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}}))
9276 {
9277 my $TypeId = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"type"};
9278 my $DVal = $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009279 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009280 if(defined $DVal and $DVal ne "")
9281 {
9282 if($TName eq "char") {
9283 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = chr($DVal);
9284 }
9285 elsif($TName eq "bool") {
9286 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$P}{"default"} = $DVal?"true":"false";
9287 }
9288 }
9289 }
9290 }
9291 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009292 if($SymbolInfo{$LibVersion}{$InfoId}{"Destructor"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009293 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009294 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
9295 and keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +04009296 and $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009297 { # support for old GCC < 4.5: skip artificial ~dtor(int __in_chrg)
9298 # + support for old ABI dumps
9299 next;
9300 }
9301 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009302 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009303 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009304 my $ClassID = $SymbolInfo{$LibVersion}{$InfoId}{"Class"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009305 my $Return = $SymbolInfo{$LibVersion}{$InfoId}{"Return"};
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009306
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009307 my $SRemangle = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009308 if(not checkDump(1, "2.12")
9309 or not checkDump(2, "2.12"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009310 { # support for old ABI dumps
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009311 if($ShortName eq "operator>>")
9312 {
9313 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9314 { # corrected mangling of operator>>
9315 $SRemangle = 1;
9316 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009317 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009318 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9319 {
9320 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
9321 and isConstType($Return, $LibVersion) and $MnglName!~/L\d+$ShortName/)
9322 { # corrected mangling of const global data
9323 # some global data is not mangled in the TU dump: qt_sine_table (Qt 4.8)
9324 # and incorrectly mangled by old ACC versions
9325 $SRemangle = 1;
9326 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009327 }
9328 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +04009329 if(not $CheckHeadersOnly)
9330 { # support for old ABI dumps
9331 if(not checkDump(1, "2.17")
9332 or not checkDump(2, "2.17"))
9333 {
9334 if($SymbolInfo{$LibVersion}{$InfoId}{"Data"})
9335 {
9336 if(not $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
9337 {
9338 if(link_symbol($ShortName, $LibVersion, "-Deps"))
9339 {
9340 $MnglName = $ShortName;
9341 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
9342 }
9343 }
9344 }
9345 }
9346 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009347 if($Remangle==1 or $SRemangle==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009348 { # support for old ABI dumps: some symbols are not mangled in old dumps
9349 # mangle both sets of symbols (old and new)
9350 # NOTE: remangling all symbols by the same mangler
9351 if($MnglName=~/\A_ZN(V|)K/)
9352 { # mangling may be incorrect on old ABI dumps
9353 # because of absent "Const" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009354 $SymbolInfo{$LibVersion}{$InfoId}{"Const"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009355 }
9356 if($MnglName=~/\A_ZN(K|)V/)
9357 { # mangling may be incorrect on old ABI dumps
9358 # because of absent "Volatile" attribute
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009359 $SymbolInfo{$LibVersion}{$InfoId}{"Volatile"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009360 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009361 if(($ClassID and $MnglName!~/\A(_Z|\?)/)
9362 or (not $ClassID and $CheckHeadersOnly)
9363 or (not $ClassID and not link_symbol($MnglName, $LibVersion, "-Deps")))
9364 { # support for old ABI dumps, GCC >= 4.0
9365 # remangling all manually mangled symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009366 if($MnglName = mangle_symbol($InfoId, $LibVersion, "GCC"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009367 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009368 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $MnglName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009369 $MangledNames{$LibVersion}{$MnglName} = 1;
9370 }
9371 }
9372 }
9373 elsif($Remangle==-1)
9374 { # remove mangling
9375 $MnglName = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009376 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009377 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009378 if(not $MnglName) {
9379 next;
9380 }
9381 if(not $CompleteSignature{$LibVersion}{$MnglName}{"MnglName"})
9382 { # NOTE: global data may enter here twice
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009383 %{$CompleteSignature{$LibVersion}{$MnglName}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9384
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009385 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009386 if(not checkDump($LibVersion, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009387 { # support for old dumps
9388 # add "Volatile" attribute
9389 if($MnglName=~/_Z(K|)V/) {
9390 $CompleteSignature{$LibVersion}{$MnglName}{"Volatile"}=1;
9391 }
9392 }
9393 # symbol and its symlink have same signatures
9394 if($SymVer{$LibVersion}{$MnglName}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +04009395 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$MnglName}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009396 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009397
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +04009398 if(my $Alias = $CompleteSignature{$LibVersion}{$MnglName}{"Alias"})
9399 {
9400 %{$CompleteSignature{$LibVersion}{$Alias}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9401 if($SymVer{$LibVersion}{$Alias}) {
9402 %{$CompleteSignature{$LibVersion}{$SymVer{$LibVersion}{$Alias}}} = %{$SymbolInfo{$LibVersion}{$InfoId}};
9403 }
9404 }
9405
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009406 # clean memory
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009407 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009408 }
9409 if($COMMON_LANGUAGE{$LibVersion} eq "C++" or $OSgroup eq "windows") {
9410 translateSymbols(keys(%{$CompleteSignature{$LibVersion}}), $LibVersion);
9411 }
9412 if($ExtendedCheck)
9413 { # --ext option
9414 addExtension($LibVersion);
9415 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009416
9417 # clean memory
9418 delete($SymbolInfo{$LibVersion});
9419
9420 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009421 { # detect allocable classes with public exported constructors
9422 # or classes with auto-generated or inline-only constructors
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009423 # and other temp info
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009424 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009425 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009426 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009427 if($CompleteSignature{$LibVersion}{$Symbol}{"Constructor"}
9428 and not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009429 { # Class() { ... } will not be exported
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009430 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009431 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009432 if($CheckHeadersOnly or link_symbol($Symbol, $LibVersion, "-Deps")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009433 $AllocableClass{$LibVersion}{$ClassName} = 1;
9434 }
9435 }
9436 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009437 if(not $CompleteSignature{$LibVersion}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009438 { # all imported class methods
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009439 if(symbolFilter($Symbol, $LibVersion, "Affected", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009440 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009441 if($CheckHeadersOnly)
9442 {
9443 if(not $CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
9444 or $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
9445 { # all symbols except non-virtual inline
9446 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
9447 }
9448 }
9449 else {
9450 $ClassMethods{"Binary"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009451 }
9452 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009453 if(symbolFilter($Symbol, $LibVersion, "Affected", "Source")) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009454 $ClassMethods{"Source"}{$LibVersion}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009455 }
9456 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009457 $ClassNames{$LibVersion}{$ClassName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009458 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009459 if(my $RetId = $CompleteSignature{$LibVersion}{$Symbol}{"Return"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009460 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009461 my %Base = get_BaseType($RetId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009462 if(defined $Base{"Type"}
9463 and $Base{"Type"}=~/Struct|Class/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009464 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009465 my $Name = $TypeInfo{$LibVersion}{$Base{"Tid"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009466 if($Name=~/<([^<>\s]+)>/)
9467 {
9468 if(my $Tid = getTypeIdByName($1, $LibVersion)) {
9469 $ReturnedClass{$LibVersion}{$Tid} = 1;
9470 }
9471 }
9472 else {
9473 $ReturnedClass{$LibVersion}{$Base{"Tid"}} = 1;
9474 }
9475 }
9476 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009477 foreach my $Num (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009478 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009479 my $PId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Num}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009480 if(get_PLevel($PId, $LibVersion)>=1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009481 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009482 if(my %Base = get_BaseType($PId, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009483 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009484 if($Base{"Type"}=~/Struct|Class/)
9485 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009486 $ParamClass{$LibVersion}{$Base{"Tid"}}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009487 foreach my $SubId (get_sub_classes($Base{"Tid"}, $LibVersion, 1))
9488 { # mark all derived classes
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009489 $ParamClass{$LibVersion}{$SubId}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009490 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009491 }
9492 }
9493 }
9494 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009495
9496 # mapping {short name => symbols}
9497 $Func_ShortName{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"ShortName"}}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009498 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009499 foreach my $MnglName (keys(%VTableClass))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009500 { # reconstruct attributes of v-tables
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009501 if(index($MnglName, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009502 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +04009503 if(my $ClassName = $VTableClass{$MnglName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009504 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009505 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
9506 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009507 $CompleteSignature{$LibVersion}{$MnglName}{"Header"} = $TypeInfo{$LibVersion}{$ClassId}{"Header"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009508 $CompleteSignature{$LibVersion}{$MnglName}{"Class"} = $ClassId;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009509 }
9510 }
9511 }
9512 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009513
9514 # types
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009515 foreach my $TypeId (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009516 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009517 if(my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009518 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009519 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"}) {
9520 $ClassNames{$LibVersion}{$TName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009521 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009522 if(defined $TypeInfo{$LibVersion}{$TypeId}{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009523 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009524 $ClassNames{$LibVersion}{$TName} = 1;
9525 foreach my $Bid (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009526 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009527 if(my $BName = $TypeInfo{$LibVersion}{$Bid}{"Name"}) {
9528 $ClassNames{$LibVersion}{$BName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009529 }
9530 }
9531 }
9532 }
9533 }
9534}
9535
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009536sub getFirst($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009537{
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009538 my ($Tid, $LibVersion) = @_;
9539 if(not $Tid) {
9540 return $Tid;
9541 }
9542
9543 if(my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"})
9544 {
9545 if($TName_Tid{$LibVersion}{$Name}) {
9546 return $TName_Tid{$LibVersion}{$Name};
9547 }
9548 }
9549
9550 return $Tid;
9551}
9552
9553sub register_SymbolUsage($$$)
9554{
9555 my ($InfoId, $UsedType, $LibVersion) = @_;
9556
9557 my %FuncInfo = %{$SymbolInfo{$LibVersion}{$InfoId}};
9558 if(my $RTid = getFirst($FuncInfo{"Return"}, $LibVersion))
9559 {
9560 register_TypeUsage($RTid, $UsedType, $LibVersion);
9561 $SymbolInfo{$LibVersion}{$InfoId}{"Return"} = $RTid;
9562 }
9563 if(my $FCid = getFirst($FuncInfo{"Class"}, $LibVersion))
9564 {
9565 register_TypeUsage($FCid, $UsedType, $LibVersion);
9566 $SymbolInfo{$LibVersion}{$InfoId}{"Class"} = $FCid;
9567
9568 if(my $ThisId = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."*const", $LibVersion))
9569 { # register "this" pointer
9570 register_TypeUsage($ThisId, $UsedType, $LibVersion);
9571 }
9572 if(my $ThisId_C = getTypeIdByName($TypeInfo{$LibVersion}{$FCid}{"Name"}."const*const", $LibVersion))
9573 { # register "this" pointer (const method)
9574 register_TypeUsage($ThisId_C, $UsedType, $LibVersion);
9575 }
9576 }
9577 foreach my $PPos (keys(%{$FuncInfo{"Param"}}))
9578 {
9579 if(my $PTid = getFirst($FuncInfo{"Param"}{$PPos}{"type"}, $LibVersion))
9580 {
9581 register_TypeUsage($PTid, $UsedType, $LibVersion);
9582 $FuncInfo{"Param"}{$PPos}{"type"} = $PTid;
9583 }
9584 }
9585 foreach my $TPos (keys(%{$FuncInfo{"TParam"}}))
9586 {
9587 my $TPName = $FuncInfo{"TParam"}{$TPos}{"name"};
9588 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
9589 register_TypeUsage($TTid, $UsedType, $LibVersion);
9590 }
9591 }
9592}
9593
9594sub register_TypeUsage($$$)
9595{
9596 my ($TypeId, $UsedType, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009597 if(not $TypeId) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009598 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009599 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009600 if($UsedType->{$TypeId})
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009601 { # already registered
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009602 return;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009603 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009604
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009605 my %TInfo = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009606 if($TInfo{"Type"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009607 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009608 if(my $NS = $TInfo{"NameSpace"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009609 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009610 if(my $NSTid = $TName_Tid{$LibVersion}{$NS}) {
9611 register_TypeUsage($NSTid, $UsedType, $LibVersion);
9612 }
9613 }
9614
9615 if($TInfo{"Type"}=~/\A(Struct|Union|Class|FuncPtr|Func|MethodPtr|FieldPtr|Enum)\Z/)
9616 {
9617 $UsedType->{$TypeId} = 1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009618 if($TInfo{"Type"}=~/\A(Struct|Class)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009619 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009620 foreach my $BaseId (keys(%{$TInfo{"Base"}})) {
9621 register_TypeUsage($BaseId, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009622 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009623 foreach my $TPos (keys(%{$TInfo{"TParam"}}))
9624 {
9625 my $TPName = $TInfo{"TParam"}{$TPos}{"name"};
9626 if(my $TTid = $TName_Tid{$LibVersion}{$TPName}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009627 register_TypeUsage($TTid, $UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009628 }
9629 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009630 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009631 foreach my $Memb_Pos (keys(%{$TInfo{"Memb"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009632 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009633 if(my $MTid = getFirst($TInfo{"Memb"}{$Memb_Pos}{"type"}, $LibVersion))
9634 {
9635 register_TypeUsage($MTid, $UsedType, $LibVersion);
9636 $TInfo{"Memb"}{$Memb_Pos}{"type"} = $MTid;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009637 }
9638 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009639 if($TInfo{"Type"} eq "FuncPtr"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009640 or $TInfo{"Type"} eq "MethodPtr"
9641 or $TInfo{"Type"} eq "Func")
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009642 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009643 if(my $RTid = $TInfo{"Return"}) {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009644 register_TypeUsage($RTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009645 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009646 foreach my $PPos (keys(%{$TInfo{"Param"}}))
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009647 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009648 if(my $PTid = $TInfo{"Param"}{$PPos}{"type"}) {
9649 register_TypeUsage($PTid, $UsedType, $LibVersion);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009650 }
9651 }
9652 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009653 if($TInfo{"Type"} eq "FieldPtr")
9654 {
9655 if(my $RTid = $TInfo{"Return"}) {
9656 register_TypeUsage($RTid, $UsedType, $LibVersion);
9657 }
9658 if(my $CTid = $TInfo{"Class"}) {
9659 register_TypeUsage($CTid, $UsedType, $LibVersion);
9660 }
9661 }
9662 if($TInfo{"Type"} eq "MethodPtr")
9663 {
9664 if(my $CTid = $TInfo{"Class"}) {
9665 register_TypeUsage($CTid, $UsedType, $LibVersion);
9666 }
9667 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009668 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009669 elsif($TInfo{"Type"}=~/\A(Const|ConstVolatile|Volatile|Pointer|Ref|Restrict|Array|Typedef)\Z/)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009670 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009671 $UsedType->{$TypeId} = 1;
9672 if(my $BTid = getFirst($TInfo{"BaseType"}, $LibVersion))
9673 {
9674 register_TypeUsage($BTid, $UsedType, $LibVersion);
9675 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $BTid;
9676 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009677 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009678 else
9679 { # Intrinsic, TemplateParam, TypeName, SizeOf, etc.
9680 $UsedType->{$TypeId} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009681 }
9682 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +04009683}
9684
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009685sub selectSymbol($$$$)
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009686{ # select symbol to check or to dump
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009687 my ($Symbol, $SInfo, $Level, $LibVersion) = @_;
9688
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009689 if($Level eq "Dump")
9690 {
9691 if($SInfo->{"Virt"} or $SInfo->{"PureVirt"})
9692 { # TODO: check if this symbol is from
9693 # base classes of other target symbols
9694 return 1;
9695 }
9696 }
9697
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009698 if(not $STDCXX_TESTING and $Symbol=~/\A(_ZS|_ZNS|_ZNKS)/)
9699 { # stdc++ interfaces
9700 return 0;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009701 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009702
9703 my $Target = 0;
9704 if(my $Header = $SInfo->{"Header"}) {
9705 $Target = (is_target_header($Header, 1) or is_target_header($Header, 2));
9706 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009707 if($ExtendedCheck)
9708 {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +04009709 if(index($Symbol, "external_func_")==0) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +04009710 $Target = 1;
9711 }
9712 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009713 if($CheckHeadersOnly or $Level eq "Source")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009714 {
9715 if($Target)
9716 {
9717 if($Level eq "Dump")
9718 { # dumped
9719 if($BinaryOnly)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009720 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009721 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009722 return 1;
9723 }
9724 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009725 else {
9726 return 1;
9727 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009728 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009729 elsif($Level eq "Source")
9730 { # checked
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009731 return 1;
9732 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009733 elsif($Level eq "Binary")
9734 { # checked
9735 if(not $SInfo->{"InLine"} or $SInfo->{"Data"}
9736 or $SInfo->{"Virt"} or $SInfo->{"PureVirt"}) {
9737 return 1;
9738 }
9739 }
9740 }
9741 }
9742 else
9743 { # library is available
9744 if(link_symbol($Symbol, $LibVersion, "-Deps"))
9745 { # exported symbols
9746 return 1;
9747 }
9748 if($Level eq "Dump")
9749 { # dumped
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009750 if($BinaryOnly)
9751 {
9752 if($SInfo->{"Data"})
9753 {
9754 if($Target) {
9755 return 1;
9756 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009757 }
9758 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009759 else
9760 { # SrcBin
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009761 if($Target) {
9762 return 1;
9763 }
9764 }
9765 }
9766 elsif($Level eq "Source")
9767 { # checked
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009768 if($SInfo->{"PureVirt"} or $SInfo->{"Data"} or $SInfo->{"InLine"}
9769 or isInLineInst($Symbol, $SInfo, $LibVersion))
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +04009770 { # skip LOCAL symbols
9771 if($Target) {
9772 return 1;
9773 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009774 }
9775 }
9776 elsif($Level eq "Binary")
9777 { # checked
9778 if($SInfo->{"PureVirt"} or $SInfo->{"Data"})
9779 {
9780 if($Target) {
9781 return 1;
9782 }
9783 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009784 }
9785 }
9786 return 0;
9787}
9788
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009789sub cleanDump($)
9790{ # clean data
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009791 my $LibVersion = $_[0];
9792 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
9793 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009794 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}}))
9795 {
9796 delete($SymbolInfo{$LibVersion}{$InfoId});
9797 next;
9798 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009799 my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009800 if(not $MnglName)
9801 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009802 delete($SymbolInfo{$LibVersion}{$InfoId});
9803 next;
9804 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +04009805 my $ShortName = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009806 if(not $ShortName)
9807 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +04009808 delete($SymbolInfo{$LibVersion}{$InfoId});
9809 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009810 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009811 if($MnglName eq $ShortName)
9812 { # remove duplicate data
9813 delete($SymbolInfo{$LibVersion}{$InfoId}{"MnglName"});
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009814 }
9815 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}})) {
9816 delete($SymbolInfo{$LibVersion}{$InfoId}{"Param"});
9817 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009818 if(not keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"TParam"}})) {
9819 delete($SymbolInfo{$LibVersion}{$InfoId}{"TParam"});
9820 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009821 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009822 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009823 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009824 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}}))
9825 {
9826 delete($TypeInfo{$LibVersion}{$Tid});
9827 next;
9828 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009829 delete($TypeInfo{$LibVersion}{$Tid}{"Tid"});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009830 foreach my $Attr ("Header", "Line", "Size", "NameSpace")
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009831 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009832 if(not $TypeInfo{$LibVersion}{$Tid}{$Attr}) {
9833 delete($TypeInfo{$LibVersion}{$Tid}{$Attr});
9834 }
9835 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +04009836 if(not keys(%{$TypeInfo{$LibVersion}{$Tid}{"TParam"}})) {
9837 delete($TypeInfo{$LibVersion}{$Tid}{"TParam"});
9838 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009839 }
9840}
9841
9842sub selectType($$)
9843{
9844 my ($Tid, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +04009845
9846 if(my $Dupl = $TypeTypedef{$LibVersion}{$Tid})
9847 {
9848 if(defined $TypeInfo{$LibVersion}{$Dupl})
9849 {
9850 if($TypeInfo{$LibVersion}{$Dupl}{"Name"} eq $TypeInfo{$LibVersion}{$Tid}{"Name"})
9851 { # duplicate
9852 return 0;
9853 }
9854 }
9855 }
9856
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009857 if(my $THeader = $TypeInfo{$LibVersion}{$Tid}{"Header"})
9858 {
9859 if(not isBuiltIn($THeader))
9860 {
9861 if($TypeInfo{$LibVersion}{$Tid}{"Type"}=~/Class|Struct|Union|Enum|Typedef/)
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009862 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009863 if(not isAnon($TypeInfo{$LibVersion}{$Tid}{"Name"}))
9864 {
9865 if(is_target_header($THeader, $LibVersion))
9866 { # from target headers
9867 if(not selfTypedef($Tid, $LibVersion)) {
9868 return 1;
9869 }
9870 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009871 }
9872 }
9873 }
9874 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009875 return 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +04009876}
9877
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009878sub remove_Unused($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009879{ # remove unused data types from the ABI dump
9880 my ($LibVersion, $Kind) = @_;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009881
9882 my %UsedType = ();
9883
9884 foreach my $InfoId (sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009885 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009886 register_SymbolUsage($InfoId, \%UsedType, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009887 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009888 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009889 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009890 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009891 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009892 next;
9893 }
9894
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009895 if($Kind eq "Extended")
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009896 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009897 if(selectType($Tid, $LibVersion))
9898 {
9899 my %Tree = ();
9900 register_TypeUsage($Tid, \%Tree, $LibVersion);
9901
9902 my $Tmpl = 0;
9903 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9904 {
9905 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9906 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9907 {
9908 $Tmpl = 1;
9909 last;
9910 }
9911 }
9912 if(not $Tmpl)
9913 {
9914 foreach (keys(%Tree)) {
9915 $UsedType{$_} = 1;
9916 }
9917 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009918 }
9919 }
9920 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009921
9922 my %Delete = ();
9923
9924 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009925 { # remove unused types
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009926 if($UsedType{$Tid})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +04009927 { # All & Extended
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009928 next;
9929 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009930
9931 if($Kind eq "Extra")
9932 {
9933 my %Tree = ();
9934 register_TypeUsage($Tid, \%Tree, $LibVersion);
9935
9936 foreach (sort {int($a)<=>int($b)} keys(%Tree))
9937 {
9938 if(defined $TypeInfo{$LibVersion}{$_}{"Template"}
9939 or $TypeInfo{$LibVersion}{$_}{"Type"} eq "TemplateParam")
9940 {
9941 $Delete{$Tid} = 1;
9942 last;
9943 }
9944 }
9945 }
9946 else
9947 {
9948 # remove type
9949 delete($TypeInfo{$LibVersion}{$Tid});
9950 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +04009951 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +04009952
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +04009953 if($Kind eq "Extra")
9954 { # remove duplicates
9955 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
9956 {
9957 if($UsedType{$Tid})
9958 { # All & Extended
9959 next;
9960 }
9961
9962 my $Name = $TypeInfo{$LibVersion}{$Tid}{"Name"};
9963
9964 if($TName_Tid{$LibVersion}{$Name} ne $Tid) {
9965 delete($TypeInfo{$LibVersion}{$Tid});
9966 }
9967 }
9968 }
9969
9970 foreach my $Tid (keys(%Delete))
9971 {
9972 delete($TypeInfo{$LibVersion}{$Tid});
9973 }
9974}
9975
9976sub check_Completeness($$)
9977{
9978 my ($Info, $LibVersion) = @_;
9979
9980 # data types
9981 if(defined $Info->{"Memb"})
9982 {
9983 foreach my $Pos (keys(%{$Info->{"Memb"}}))
9984 {
9985 if(defined $Info->{"Memb"}{$Pos}{"type"}) {
9986 check_TypeInfo($Info->{"Memb"}{$Pos}{"type"}, $LibVersion);
9987 }
9988 }
9989 }
9990 if(defined $Info->{"Base"})
9991 {
9992 foreach my $Bid (keys(%{$Info->{"Base"}})) {
9993 check_TypeInfo($Bid, $LibVersion);
9994 }
9995 }
9996 if(defined $Info->{"BaseType"}) {
9997 check_TypeInfo($Info->{"BaseType"}, $LibVersion);
9998 }
9999 if(defined $Info->{"TParam"})
10000 {
10001 foreach my $Pos (keys(%{$Info->{"TParam"}}))
10002 {
10003 my $TName = $Info->{"TParam"}{$Pos}{"name"};
10004 if($TName=~/\A\(.+\)(true|false|\d.*)\Z/) {
10005 next;
10006 }
10007 if($TName eq "_BoolType") {
10008 next;
10009 }
10010 if($TName=~/\Asizeof\(/) {
10011 next;
10012 }
10013 if(my $Tid = $TName_Tid{$LibVersion}{$TName}) {
10014 check_TypeInfo($Tid, $LibVersion);
10015 }
10016 else
10017 {
10018 if(defined $Debug) {
10019 printMsg("WARNING", "missed type $TName");
10020 }
10021 }
10022 }
10023 }
10024
10025 # symbols
10026 if(defined $Info->{"Param"})
10027 {
10028 foreach my $Pos (keys(%{$Info->{"Param"}}))
10029 {
10030 if(defined $Info->{"Param"}{$Pos}{"type"}) {
10031 check_TypeInfo($Info->{"Param"}{$Pos}{"type"}, $LibVersion);
10032 }
10033 }
10034 }
10035 if(defined $Info->{"Return"}) {
10036 check_TypeInfo($Info->{"Return"}, $LibVersion);
10037 }
10038 if(defined $Info->{"Class"}) {
10039 check_TypeInfo($Info->{"Class"}, $LibVersion);
10040 }
10041}
10042
10043sub check_TypeInfo($$)
10044{
10045 my ($Tid, $LibVersion) = @_;
10046
10047 if(defined $CheckedTypeInfo{$LibVersion}{$Tid}) {
10048 return;
10049 }
10050 $CheckedTypeInfo{$LibVersion}{$Tid} = 1;
10051
10052 if(defined $TypeInfo{$LibVersion}{$Tid})
10053 {
10054 if(not $TypeInfo{$LibVersion}{$Tid}{"Name"}) {
10055 printMsg("ERROR", "missed type name ($Tid)");
10056 }
10057 check_Completeness($TypeInfo{$LibVersion}{$Tid}, $LibVersion);
10058 }
10059 else {
10060 printMsg("ERROR", "missed type id $Tid");
10061 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010062}
10063
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010064sub selfTypedef($$)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010065{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010066 my ($TypeId, $LibVersion) = @_;
10067 my %Type = get_Type($TypeId, $LibVersion);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010068 if($Type{"Type"} eq "Typedef")
10069 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010070 my %Base = get_OneStep_BaseType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010071 if($Base{"Type"}=~/Class|Struct/)
10072 {
10073 if($Type{"Name"} eq $Base{"Name"}) {
10074 return 1;
10075 }
10076 elsif($Type{"Name"}=~/::(\w+)\Z/)
10077 {
10078 if($Type{"Name"} eq $Base{"Name"}."::".$1)
10079 { # QPointer<QWidget>::QPointer
10080 return 1;
10081 }
10082 }
10083 }
10084 }
10085 return 0;
10086}
10087
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010088sub addExtension($)
10089{
10090 my $LibVersion = $_[0];
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010091 foreach my $Tid (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010092 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010093 if(selectType($Tid, $LibVersion))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010094 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010095 my $TName = $TypeInfo{$LibVersion}{$Tid}{"Name"};
10096 $TName=~s/\A(struct|union|class|enum) //;
10097 my $Symbol = "external_func_".$TName;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010098
10099 %{$CompleteSignature{$LibVersion}{$Symbol}} = (
10100 "Header" => "extended.h",
10101 "ShortName" => $Symbol,
10102 "MnglName" => $Symbol,
10103 "Param" => { 0 => { "type"=>$Tid, "name"=>"p1" } }
10104 );
10105
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010106 $ExtendedSymbols{$Symbol} = 1;
10107 $CheckedSymbols{"Binary"}{$Symbol} = 1;
10108 $CheckedSymbols{"Source"}{$Symbol} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010109 }
10110 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040010111 $ExtendedSymbols{"external_func_0"} = 1;
10112 $CheckedSymbols{"Binary"}{"external_func_0"} = 1;
10113 $CheckedSymbols{"Source"}{"external_func_0"} = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010114}
10115
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010116sub findMethod($$$)
10117{
10118 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010119 foreach my $BaseClass_Id (keys(%{$TypeInfo{$LibVersion}{$ClassId}{"Base"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010120 {
10121 if(my $VirtMethodInClass = findMethod_Class($VirtFunc, $BaseClass_Id, $LibVersion)) {
10122 return $VirtMethodInClass;
10123 }
10124 elsif(my $VirtMethodInBaseClasses = findMethod($VirtFunc, $BaseClass_Id, $LibVersion)) {
10125 return $VirtMethodInBaseClasses;
10126 }
10127 }
10128 return "";
10129}
10130
10131sub findMethod_Class($$$)
10132{
10133 my ($VirtFunc, $ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010134 my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010135 return "" if(not defined $VirtualTable{$LibVersion}{$ClassName});
10136 my $TargetSuffix = get_symbol_suffix($VirtFunc, 1);
10137 my $TargetShortName = $CompleteSignature{$LibVersion}{$VirtFunc}{"ShortName"};
10138 foreach my $Candidate (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10139 { # search for interface with the same parameters suffix (overridden)
10140 if($TargetSuffix eq get_symbol_suffix($Candidate, 1))
10141 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010142 if($CompleteSignature{$LibVersion}{$VirtFunc}{"Destructor"})
10143 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010144 if($CompleteSignature{$LibVersion}{$Candidate}{"Destructor"})
10145 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010146 if(($VirtFunc=~/D0E/ and $Candidate=~/D0E/)
10147 or ($VirtFunc=~/D1E/ and $Candidate=~/D1E/)
10148 or ($VirtFunc=~/D2E/ and $Candidate=~/D2E/)) {
10149 return $Candidate;
10150 }
10151 }
10152 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040010153 else
10154 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010155 if($TargetShortName eq $CompleteSignature{$LibVersion}{$Candidate}{"ShortName"}) {
10156 return $Candidate;
10157 }
10158 }
10159 }
10160 }
10161 return "";
10162}
10163
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010164sub registerVTable($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010165{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010166 my $LibVersion = $_[0];
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010167 foreach my $Symbol (keys(%{$CompleteSignature{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010168 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010169 if($CompleteSignature{$LibVersion}{$Symbol}{"Virt"}
10170 or $CompleteSignature{$LibVersion}{$Symbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010171 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010172 my $ClassName = $TypeInfo{$LibVersion}{$CompleteSignature{$LibVersion}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010173 next if(not $STDCXX_TESTING and $ClassName=~/\A(std::|__cxxabi)/);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010174 if($CompleteSignature{$LibVersion}{$Symbol}{"Destructor"}
10175 and $Symbol=~/D2E/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010176 { # pure virtual D2-destructors are marked as "virt" in the dump
10177 # virtual D2-destructors are NOT marked as "virt" in the dump
10178 # both destructors are not presented in the v-table
10179 next;
10180 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010181 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010182 $VirtualTable{$LibVersion}{$ClassName}{$MnglName} = 1;
10183 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010184 }
10185}
10186
10187sub registerOverriding($)
10188{
10189 my $LibVersion = $_[0];
10190 my @Classes = keys(%{$VirtualTable{$LibVersion}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010191 @Classes = sort {int($TName_Tid{$LibVersion}{$a})<=>int($TName_Tid{$LibVersion}{$b})} @Classes;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010192 foreach my $ClassName (@Classes)
10193 {
10194 foreach my $VirtFunc (keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
10195 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010196 if($CompleteSignature{$LibVersion}{$VirtFunc}{"PureVirt"})
10197 { # pure virtuals
10198 next;
10199 }
10200 my $ClassId = $TName_Tid{$LibVersion}{$ClassName};
10201 if(my $Overridden = findMethod($VirtFunc, $ClassId, $LibVersion))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010202 {
10203 if($CompleteSignature{$LibVersion}{$Overridden}{"Virt"}
10204 or $CompleteSignature{$LibVersion}{$Overridden}{"PureVirt"})
10205 { # both overridden virtual methods
10206 # and implemented pure virtual methods
10207 $CompleteSignature{$LibVersion}{$VirtFunc}{"Override"} = $Overridden;
10208 $OverriddenMethods{$LibVersion}{$Overridden}{$VirtFunc} = 1;
10209 delete($VirtualTable{$LibVersion}{$ClassName}{$VirtFunc}); # remove from v-table model
10210 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010211 }
10212 }
10213 if(not keys(%{$VirtualTable{$LibVersion}{$ClassName}})) {
10214 delete($VirtualTable{$LibVersion}{$ClassName});
10215 }
10216 }
10217}
10218
10219sub setVirtFuncPositions($)
10220{
10221 my $LibVersion = $_[0];
10222 foreach my $ClassName (keys(%{$VirtualTable{$LibVersion}}))
10223 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010224 my ($Num, $Rel) = (1, 0);
10225
10226 if(my @Funcs = sort keys(%{$VirtualTable{$LibVersion}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010227 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010228 if($UsedDump{$LibVersion}{"DWARF"}) {
10229 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @Funcs;
10230 }
10231 else {
10232 @Funcs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @Funcs;
10233 }
10234 foreach my $VirtFunc (@Funcs)
10235 {
10236 if($UsedDump{$LibVersion}{"DWARF"}) {
10237 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $CompleteSignature{$LibVersion}{$VirtFunc}{"VirtPos"};
10238 }
10239 else {
10240 $VirtualTable{$LibVersion}{$ClassName}{$VirtFunc} = $Num++;
10241 }
10242
10243 # set relative positions
10244 if(defined $VirtualTable{1}{$ClassName} and defined $VirtualTable{1}{$ClassName}{$VirtFunc}
10245 and defined $VirtualTable{2}{$ClassName} and defined $VirtualTable{2}{$ClassName}{$VirtFunc})
10246 { # relative position excluding added and removed virtual functions
10247 if(not $CompleteSignature{1}{$VirtFunc}{"Override"}
10248 and not $CompleteSignature{2}{$VirtFunc}{"Override"}) {
10249 $CompleteSignature{$LibVersion}{$VirtFunc}{"RelPos"} = $Rel++;
10250 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010251 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010253 }
10254 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010255 foreach my $ClassName (keys(%{$ClassNames{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010256 {
10257 my $AbsNum = 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010258 foreach my $VirtFunc (getVTable_Model($TName_Tid{$LibVersion}{$ClassName}, $LibVersion)) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010259 $VirtualTable_Model{$LibVersion}{$ClassName}{$VirtFunc} = $AbsNum++;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010260 }
10261 }
10262}
10263
10264sub get_sub_classes($$$)
10265{
10266 my ($ClassId, $LibVersion, $Recursive) = @_;
10267 return () if(not defined $Class_SubClasses{$LibVersion}{$ClassId});
10268 my @Subs = ();
10269 foreach my $SubId (keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
10270 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010271 if($Recursive)
10272 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010273 foreach my $SubSubId (get_sub_classes($SubId, $LibVersion, $Recursive)) {
10274 push(@Subs, $SubSubId);
10275 }
10276 }
10277 push(@Subs, $SubId);
10278 }
10279 return @Subs;
10280}
10281
10282sub get_base_classes($$$)
10283{
10284 my ($ClassId, $LibVersion, $Recursive) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010285 my %ClassType = get_Type($ClassId, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010286 return () if(not defined $ClassType{"Base"});
10287 my @Bases = ();
10288 foreach my $BaseId (sort {int($ClassType{"Base"}{$a}{"pos"})<=>int($ClassType{"Base"}{$b}{"pos"})}
10289 keys(%{$ClassType{"Base"}}))
10290 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010291 if($Recursive)
10292 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010293 foreach my $SubBaseId (get_base_classes($BaseId, $LibVersion, $Recursive)) {
10294 push(@Bases, $SubBaseId);
10295 }
10296 }
10297 push(@Bases, $BaseId);
10298 }
10299 return @Bases;
10300}
10301
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010302sub getVTable_Model($$)
10303{ # return an ordered list of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010304 my ($ClassId, $LibVersion) = @_;
10305 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10306 my @Elements = ();
10307 foreach my $BaseId (@Bases, $ClassId)
10308 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010309 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010310 {
10311 if(defined $VirtualTable{$LibVersion}{$BName})
10312 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040010313 my @VFuncs = keys(%{$VirtualTable{$LibVersion}{$BName}});
10314 if($UsedDump{$LibVersion}{"DWARF"}) {
10315 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"VirtPos"}) <=> int($CompleteSignature{$LibVersion}{$b}{"VirtPos"})} @VFuncs;
10316 }
10317 else {
10318 @VFuncs = sort {int($CompleteSignature{$LibVersion}{$a}{"Line"}) <=> int($CompleteSignature{$LibVersion}{$b}{"Line"})} @VFuncs;
10319 }
10320 foreach my $VFunc (@VFuncs) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010321 push(@Elements, $VFunc);
10322 }
10323 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010324 }
10325 }
10326 return @Elements;
10327}
10328
10329sub getVShift($$)
10330{
10331 my ($ClassId, $LibVersion) = @_;
10332 my @Bases = get_base_classes($ClassId, $LibVersion, 1);
10333 my $VShift = 0;
10334 foreach my $BaseId (@Bases)
10335 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010336 if(my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010337 {
10338 if(defined $VirtualTable{$LibVersion}{$BName}) {
10339 $VShift+=keys(%{$VirtualTable{$LibVersion}{$BName}});
10340 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010341 }
10342 }
10343 return $VShift;
10344}
10345
10346sub getShift($$)
10347{
10348 my ($ClassId, $LibVersion) = @_;
10349 my @Bases = get_base_classes($ClassId, $LibVersion, 0);
10350 my $Shift = 0;
10351 foreach my $BaseId (@Bases)
10352 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010353 if(my $Size = $TypeInfo{$LibVersion}{$BaseId}{"Size"})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010354 {
10355 if($Size!=1)
10356 { # not empty base class
10357 $Shift+=$Size;
10358 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010359 }
10360 }
10361 return $Shift;
10362}
10363
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010364sub getVTable_Size($$)
10365{ # number of v-table elements
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010366 my ($ClassName, $LibVersion) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010367 my $Size = 0;
10368 # three approaches
10369 if(not $Size)
10370 { # real size
10371 if(my %VTable = getVTable_Real($ClassName, $LibVersion)) {
10372 $Size = keys(%VTable);
10373 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010374 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010375 if(not $Size)
10376 { # shared library symbol size
10377 if($Size = getSymbolSize($ClassVTable{$ClassName}, $LibVersion)) {
10378 $Size /= $WORD_SIZE{$LibVersion};
10379 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010380 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010381 if(not $Size)
10382 { # model size
10383 if(defined $VirtualTable_Model{$LibVersion}{$ClassName}) {
10384 $Size = keys(%{$VirtualTable_Model{$LibVersion}{$ClassName}}) + 2;
10385 }
10386 }
10387 return $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010388}
10389
10390sub isCopyingClass($$)
10391{
10392 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010393 return $TypeInfo{$LibVersion}{$TypeId}{"Copied"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010394}
10395
10396sub isLeafClass($$)
10397{
10398 my ($ClassId, $LibVersion) = @_;
10399 return (not keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}));
10400}
10401
10402sub havePubFields($)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010403{ # check structured type for public fields
10404 return isAccessible($_[0], {}, 0, -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010405}
10406
10407sub isAccessible($$$$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010408{ # check interval in structured type for public fields
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010409 my ($TypePtr, $Skip, $Start, $End) = @_;
10410 return 0 if(not $TypePtr);
10411 if($End==-1) {
10412 $End = keys(%{$TypePtr->{"Memb"}})-1;
10413 }
10414 foreach my $MemPos (keys(%{$TypePtr->{"Memb"}}))
10415 {
10416 if($Skip and $Skip->{$MemPos})
10417 { # skip removed/added fields
10418 next;
10419 }
10420 if(int($MemPos)>=$Start and int($MemPos)<=$End)
10421 {
10422 if(isPublic($TypePtr, $MemPos)) {
10423 return ($MemPos+1);
10424 }
10425 }
10426 }
10427 return 0;
10428}
10429
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010430sub isReserved($)
10431{ # reserved fields == private
10432 my $MName = $_[0];
10433 if($MName=~/reserved|padding|f_spare/i) {
10434 return 1;
10435 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010436 if($MName=~/\A[_]*(spare|pad|unused)[_\d]*\Z/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010437 return 1;
10438 }
10439 if($MName=~/(pad\d+)/i) {
10440 return 1;
10441 }
10442 return 0;
10443}
10444
10445sub isPublic($$)
10446{
10447 my ($TypePtr, $FieldPos) = @_;
10448 return 0 if(not $TypePtr);
10449 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos});
10450 return 0 if(not defined $TypePtr->{"Memb"}{$FieldPos}{"name"});
10451 if(not $TypePtr->{"Memb"}{$FieldPos}{"access"})
10452 { # by name in C language
10453 # FIXME: add other methods to detect private members
10454 my $MName = $TypePtr->{"Memb"}{$FieldPos}{"name"};
10455 if($MName=~/priv|abidata|parent_object/i)
10456 { # C-styled private data
10457 return 0;
10458 }
10459 if(lc($MName) eq "abi")
10460 { # ABI information/reserved field
10461 return 0;
10462 }
10463 if(isReserved($MName))
10464 { # reserved fields
10465 return 0;
10466 }
10467 return 1;
10468 }
10469 elsif($TypePtr->{"Memb"}{$FieldPos}{"access"} ne "private")
10470 { # by access in C++ language
10471 return 1;
10472 }
10473 return 0;
10474}
10475
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010476sub getVTable_Real($$)
10477{
10478 my ($ClassName, $LibVersion) = @_;
10479 if(my $ClassId = $TName_Tid{$LibVersion}{$ClassName})
10480 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010481 my %Type = get_Type($ClassId, $LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010482 if(defined $Type{"VTable"}) {
10483 return %{$Type{"VTable"}};
10484 }
10485 }
10486 return ();
10487}
10488
10489sub cmpVTables($)
10490{
10491 my $ClassName = $_[0];
10492 my $Res = cmpVTables_Real($ClassName, 1);
10493 if($Res==-1) {
10494 $Res = cmpVTables_Model($ClassName);
10495 }
10496 return $Res;
10497}
10498
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010499sub cmpVTables_Model($)
10500{
10501 my $ClassName = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010502 foreach my $Symbol (keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010503 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010504 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010505 return 1;
10506 }
10507 }
10508 return 0;
10509}
10510
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010511sub cmpVTables_Real($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010512{
10513 my ($ClassName, $Strong) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010514 if(defined $Cache{"cmpVTables_Real"}{$Strong}{$ClassName}) {
10515 return $Cache{"cmpVTables_Real"}{$Strong}{$ClassName};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010516 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010517 my %VTable_Old = getVTable_Real($ClassName, 1);
10518 my %VTable_New = getVTable_Real($ClassName, 2);
10519 if(not %VTable_Old or not %VTable_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010520 { # old ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010521 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = -1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010522 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010523 my %Indexes = map {$_=>1} (keys(%VTable_Old), keys(%VTable_New));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010524 foreach my $Offset (sort {int($a)<=>int($b)} keys(%Indexes))
10525 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010526 if(not defined $VTable_Old{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010527 { # v-table v.1 < v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010528 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = $Strong);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010529 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010530 my $Entry1 = $VTable_Old{$Offset};
10531 if(not defined $VTable_New{$Offset})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010532 { # v-table v.1 > v-table v.2
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010533 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = ($Strong or $Entry1!~/__cxa_pure_virtual/));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010534 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010535 my $Entry2 = $VTable_New{$Offset};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010536 $Entry1 = simpleVEntry($Entry1);
10537 $Entry2 = simpleVEntry($Entry2);
10538 if($Entry1 ne $Entry2)
10539 { # register as changed
10540 if($Entry1=~/::([^:]+)\Z/)
10541 {
10542 my $M1 = $1;
10543 if($Entry2=~/::([^:]+)\Z/)
10544 {
10545 my $M2 = $1;
10546 if($M1 eq $M2)
10547 { # overridden
10548 next;
10549 }
10550 }
10551 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040010552 if(differentDumps("G"))
10553 {
10554 if($Entry1=~/\A\-(0x|\d+)/ and $Entry2=~/\A\-(0x|\d+)/)
10555 {
10556 # GCC 4.6.1: -0x00000000000000010
10557 # GCC 4.7.0: -16
10558 next;
10559 }
10560 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010561 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010562 }
10563 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010564 return ($Cache{"cmpVTables_Real"}{$Strong}{$ClassName} = 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010565}
10566
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010567sub mergeVTables($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010568{ # merging v-tables without diagnostics
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010569 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010570 foreach my $ClassName (keys(%{$VirtualTable{1}}))
10571 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010572 if($VTableChanged_M{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010573 { # already registered
10574 next;
10575 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010576 if(cmpVTables_Real($ClassName, 0)==1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010577 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010578 my @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010579 foreach my $Symbol (@Affected)
10580 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010581 %{$CompatProblems{$Level}{$Symbol}{"Virtual_Table_Changed_Unknown"}{$ClassName}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010582 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010583 "Target"=>$ClassName);
10584 }
10585 }
10586 }
10587}
10588
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010589sub mergeBases($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010590{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010591 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010592 foreach my $ClassName (keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010593 { # detect added and removed virtual functions
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010594 my $ClassId = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010595 next if(not $ClassId);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010596 if(defined $VirtualTable{2}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010597 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010598 foreach my $Symbol (keys(%{$VirtualTable{2}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010599 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010600 if($TName_Tid{1}{$ClassName}
10601 and not defined $VirtualTable{1}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010602 { # added to v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010603 if(defined $CompleteSignature{1}{$Symbol}
10604 and $CompleteSignature{1}{$Symbol}{"Virt"})
10605 { # override some method in v.1
10606 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010607 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010608 $AddedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010609 }
10610 }
10611 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010612 if(defined $VirtualTable{1}{$ClassName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010613 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010614 foreach my $Symbol (keys(%{$VirtualTable{1}{$ClassName}}))
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010615 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010616 if($TName_Tid{2}{$ClassName}
10617 and not defined $VirtualTable{2}{$ClassName}{$Symbol})
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010618 { # removed from v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010619 if(defined $CompleteSignature{2}{$Symbol}
10620 and $CompleteSignature{2}{$Symbol}{"Virt"})
10621 { # override some method in v.2
10622 next;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040010623 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010624 $RemovedInt_Virt{$Level}{$ClassName}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010625 }
10626 }
10627 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010628 if($Level eq "Binary")
10629 { # Binary-level
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010630 my %Class_Type = get_Type($ClassId, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010631 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$ClassName}}))
10632 { # check replacements, including pure virtual methods
10633 my $AddedPos = $VirtualTable{2}{$ClassName}{$AddedVFunc};
10634 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010635 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010636 my $RemovedPos = $VirtualTable{1}{$ClassName}{$RemovedVFunc};
10637 if($AddedPos==$RemovedPos)
10638 {
10639 $VirtualReplacement{$AddedVFunc} = $RemovedVFunc;
10640 $VirtualReplacement{$RemovedVFunc} = $AddedVFunc;
10641 last; # other methods will be reported as "added" or "removed"
10642 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010643 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010644 if(my $RemovedVFunc = $VirtualReplacement{$AddedVFunc})
10645 {
10646 if(lc($AddedVFunc) eq lc($RemovedVFunc))
10647 { # skip: DomUi => DomUI parameter (Qt 4.2.3 to 4.3.0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010648 next;
10649 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010650 my $ProblemType = "Virtual_Replacement";
10651 my @Affected = ($RemovedVFunc);
10652 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
10653 { # pure methods
10654 if(not isUsedClass($ClassId, 1, $Level))
10655 { # not a parameter of some exported method
10656 next;
10657 }
10658 $ProblemType = "Pure_Virtual_Replacement";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010659
10660 # affected all methods (both virtual and non-virtual ones)
10661 @Affected = (keys(%{$ClassMethods{$Level}{1}{$ClassName}}));
10662 push(@Affected, keys(%{$OverriddenMethods{1}{$RemovedVFunc}}));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010663 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010664 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010665 foreach my $AffectedInt (@Affected)
10666 {
10667 if($CompleteSignature{1}{$AffectedInt}{"PureVirt"})
10668 { # affected exported methods only
10669 next;
10670 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010671 if(not symbolFilter($AffectedInt, 1, "Affected", $Level)) {
10672 next;
10673 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010674 %{$CompatProblems{$Level}{$AffectedInt}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
10675 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010676 "Target"=>get_Signature($AddedVFunc, 2),
10677 "Old_Value"=>get_Signature($RemovedVFunc, 1));
10678 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010679 }
10680 }
10681 }
10682 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010683 if(not checkDump(1, "2.0")
10684 or not checkDump(2, "2.0"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010685 { # support for old ABI dumps
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010686 # "Base" attribute introduced in ACC 1.22 (ABI dump 2.0 format)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010687 return;
10688 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010689 foreach my $ClassName (sort keys(%{$ClassNames{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010690 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010691 my $ClassId_Old = $TName_Tid{1}{$ClassName};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010692 next if(not $ClassId_Old);
10693 if(not isCreatable($ClassId_Old, 1))
10694 { # skip classes without public constructors (including auto-generated)
10695 # example: class has only a private exported or private inline constructor
10696 next;
10697 }
10698 if($ClassName=~/>/)
10699 { # skip affected template instances
10700 next;
10701 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010702 my %Class_Old = get_Type($ClassId_Old, 1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010703 my $ClassId_New = $TName_Tid{2}{$ClassName};
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010704 if(not $ClassId_New) {
10705 next;
10706 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010707 my %Class_New = get_Type($ClassId_New, 2);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010708 if($Class_New{"Type"}!~/Class|Struct/)
10709 { # became typedef
10710 if($Level eq "Binary") {
10711 next;
10712 }
10713 if($Level eq "Source")
10714 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010715 %Class_New = get_PureType($ClassId_New, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010716 if($Class_New{"Type"}!~/Class|Struct/) {
10717 next;
10718 }
10719 $ClassId_New = $Class_New{"Tid"};
10720 }
10721 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010722 my @Bases_Old = sort {$Class_Old{"Base"}{$a}{"pos"}<=>$Class_Old{"Base"}{$b}{"pos"}} keys(%{$Class_Old{"Base"}});
10723 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 +040010724
10725 my %Tr_Old = map {$TypeInfo{1}{$_}{"Name"} => uncover_typedefs($TypeInfo{1}{$_}{"Name"}, 1)} @Bases_Old;
10726 my %Tr_New = map {$TypeInfo{2}{$_}{"Name"} => uncover_typedefs($TypeInfo{2}{$_}{"Name"}, 2)} @Bases_New;
10727
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010728 my ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010729 my %BasePos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @Bases_Old;
10730 my %BasePos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @Bases_New;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010731 my %ShortBase_Old = map {get_ShortClass($_, 1) => 1} @Bases_Old;
10732 my %ShortBase_New = map {get_ShortClass($_, 2) => 1} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010733 my $Shift_Old = getShift($ClassId_Old, 1);
10734 my $Shift_New = getShift($ClassId_New, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010735 my %BaseId_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @Bases_New;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010736 my ($Added, $Removed) = (0, 0);
10737 my @StableBases_Old = ();
10738 foreach my $BaseId (@Bases_Old)
10739 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010740 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010741 if($BasePos_New{$Tr_Old{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010742 push(@StableBases_Old, $BaseId);
10743 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010744 elsif(not $ShortBase_New{$Tr_Old{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010745 and not $ShortBase_New{get_ShortClass($BaseId, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010746 { # removed base
10747 # excluding namespace::SomeClass to SomeClass renaming
10748 my $ProblemKind = "Removed_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010749 if($Level eq "Binary")
10750 { # Binary-level
10751 if($Shift_Old ne $Shift_New)
10752 { # affected fields
10753 if(havePubFields(\%Class_Old)) {
10754 $ProblemKind .= "_And_Shift";
10755 }
10756 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10757 $ProblemKind .= "_And_Size";
10758 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010759 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010760 if(keys(%{$VirtualTable_Model{1}{$BaseName}})
10761 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010762 { # affected v-table
10763 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010764 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010765 }
10766 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010767 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010768 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10769 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010770 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10771 {
10772 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10773 if($ProblemKind=~/VTable/) {
10774 $VTableChanged_M{$SubName}=1;
10775 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010776 }
10777 }
10778 foreach my $Interface (@Affected)
10779 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010780 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10781 next;
10782 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010783 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010784 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010785 "Target"=>$BaseName,
10786 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10787 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10788 "Shift"=>abs($Shift_New-$Shift_Old) );
10789 }
10790 $Removed+=1;
10791 }
10792 }
10793 my @StableBases_New = ();
10794 foreach my $BaseId (@Bases_New)
10795 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010796 my $BaseName = $TypeInfo{2}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010797 if($BasePos_Old{$Tr_New{$BaseName}}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010798 push(@StableBases_New, $BaseId);
10799 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010800 elsif(not $ShortBase_Old{$Tr_New{$BaseName}}
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040010801 and not $ShortBase_Old{get_ShortClass($BaseId, 2)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010802 { # added base
10803 # excluding namespace::SomeClass to SomeClass renaming
10804 my $ProblemKind = "Added_Base_Class";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010805 if($Level eq "Binary")
10806 { # Binary-level
10807 if($Shift_Old ne $Shift_New)
10808 { # affected fields
10809 if(havePubFields(\%Class_Old)) {
10810 $ProblemKind .= "_And_Shift";
10811 }
10812 elsif($Class_Old{"Size"} ne $Class_New{"Size"}) {
10813 $ProblemKind .= "_And_Size";
10814 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010815 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010816 if(keys(%{$VirtualTable_Model{2}{$BaseName}})
10817 and cmpVTables($ClassName)==1)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010818 { # affected v-table
10819 $ProblemKind .= "_And_VTable";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010820 $VTableChanged_M{$ClassName}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010821 }
10822 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010823 my @Affected = keys(%{$ClassMethods{$Level}{1}{$ClassName}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010824 foreach my $SubId (get_sub_classes($ClassId_Old, 1, 1))
10825 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010826 if(my $SubName = $TypeInfo{1}{$SubId}{"Name"})
10827 {
10828 push(@Affected, keys(%{$ClassMethods{$Level}{1}{$SubName}}));
10829 if($ProblemKind=~/VTable/) {
10830 $VTableChanged_M{$SubName}=1;
10831 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010832 }
10833 }
10834 foreach my $Interface (@Affected)
10835 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010836 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10837 next;
10838 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010839 %{$CompatProblems{$Level}{$Interface}{$ProblemKind}{"this"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010840 "Type_Name"=>$ClassName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010841 "Target"=>$BaseName,
10842 "Old_Size"=>$Class_Old{"Size"}*$BYTE_SIZE,
10843 "New_Size"=>$Class_New{"Size"}*$BYTE_SIZE,
10844 "Shift"=>abs($Shift_New-$Shift_Old) );
10845 }
10846 $Added+=1;
10847 }
10848 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010849 if($Level eq "Binary")
10850 { # Binary-level
10851 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010852 my %BaseRelPos_Old = map {$Tr_Old{$TypeInfo{1}{$_}{"Name"}} => $BNum1++} @StableBases_Old;
10853 my %BaseRelPos_New = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $BNum2++} @StableBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010854 foreach my $BaseId (@Bases_Old)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010855 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010856 my $BaseName = $TypeInfo{1}{$BaseId}{"Name"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010857 if(my $NewPos = $BaseRelPos_New{$Tr_Old{$BaseName}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010858 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010859 my $BaseNewId = $BaseId_New{$Tr_Old{$BaseName}};
10860 my $OldPos = $BaseRelPos_Old{$Tr_Old{$BaseName}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010861 if($NewPos!=$OldPos)
10862 { # changed position of the base class
10863 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010864 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010865 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10866 next;
10867 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010868 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Position"}{"this"}}=(
10869 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010870 "Target"=>$BaseName,
10871 "Old_Value"=>$OldPos-1,
10872 "New_Value"=>$NewPos-1 );
10873 }
10874 }
10875 if($Class_Old{"Base"}{$BaseId}{"virtual"}
10876 and not $Class_New{"Base"}{$BaseNewId}{"virtual"})
10877 { # became non-virtual base
10878 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10879 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010880 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10881 next;
10882 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010883 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Non_Virtually_Inherited"}{"this->".$BaseName}}=(
10884 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010885 "Target"=>$BaseName );
10886 }
10887 }
10888 elsif(not $Class_Old{"Base"}{$BaseId}{"virtual"}
10889 and $Class_New{"Base"}{$BaseNewId}{"virtual"})
10890 { # became virtual base
10891 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10892 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010893 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10894 next;
10895 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010896 %{$CompatProblems{$Level}{$Interface}{"Base_Class_Became_Virtually_Inherited"}{"this->".$BaseName}}=(
10897 "Type_Name"=>$ClassName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010898 "Target"=>$BaseName );
10899 }
10900 }
10901 }
10902 }
10903 # detect size changes in base classes
10904 if($Shift_Old!=$Shift_New)
10905 { # size of allocable class
10906 foreach my $BaseId (@StableBases_Old)
10907 { # search for changed base
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010908 my %BaseType = get_Type($BaseId, 1);
10909 my $Size_Old = $TypeInfo{1}{$BaseId}{"Size"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010910 my $Size_New = $TypeInfo{2}{$BaseId_New{$Tr_Old{$BaseType{"Name"}}}}{"Size"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010911 if($Size_Old ne $Size_New
10912 and $Size_Old and $Size_New)
10913 {
10914 my $ProblemType = "";
10915 if(isCopyingClass($BaseId, 1)) {
10916 $ProblemType = "Size_Of_Copying_Class";
10917 }
10918 elsif($AllocableClass{1}{$BaseType{"Name"}})
10919 {
10920 if($Size_New>$Size_Old)
10921 { # increased size
10922 $ProblemType = "Size_Of_Allocable_Class_Increased";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010923 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010924 else
10925 { # decreased size
10926 $ProblemType = "Size_Of_Allocable_Class_Decreased";
10927 if(not havePubFields(\%Class_Old))
10928 { # affected class has no public members
10929 next;
10930 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010931 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010932 }
10933 next if(not $ProblemType);
10934 foreach my $Interface (keys(%{$ClassMethods{$Level}{1}{$ClassName}}))
10935 { # base class size changes affecting current class
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040010936 if(not symbolFilter($Interface, 1, "Affected", $Level)) {
10937 next;
10938 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010939 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{"this->".$BaseType{"Name"}}}=(
10940 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010941 "Target"=>$BaseType{"Name"},
10942 "Old_Size"=>$Size_Old*$BYTE_SIZE,
10943 "New_Size"=>$Size_New*$BYTE_SIZE );
10944 }
10945 }
10946 }
10947 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010948 if(defined $VirtualTable_Model{1}{$ClassName}
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010949 and cmpVTables_Real($ClassName, 1)==1
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010950 and my @VFunctions = keys(%{$VirtualTable_Model{1}{$ClassName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010951 { # compare virtual tables size in base classes
10952 my $VShift_Old = getVShift($ClassId_Old, 1);
10953 my $VShift_New = getVShift($ClassId_New, 2);
10954 if($VShift_Old ne $VShift_New)
10955 { # changes in the base class or changes in the list of base classes
10956 my @AllBases_Old = get_base_classes($ClassId_Old, 1, 1);
10957 my @AllBases_New = get_base_classes($ClassId_New, 2, 1);
10958 ($BNum1, $BNum2) = (1, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010959 my %StableBase = map {$Tr_New{$TypeInfo{2}{$_}{"Name"}} => $_} @AllBases_New;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010960 foreach my $BaseId (@AllBases_Old)
10961 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040010962 my %BaseType = get_Type($BaseId, 1);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010963 if(not $StableBase{$Tr_Old{$BaseType{"Name"}}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010964 { # lost base
10965 next;
10966 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010967 my $VSize_Old = getVTable_Size($BaseType{"Name"}, 1);
10968 my $VSize_New = getVTable_Size($BaseType{"Name"}, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010969 if($VSize_Old!=$VSize_New)
10970 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010971 foreach my $Symbol (@VFunctions)
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040010972 { # TODO: affected non-virtual methods?
10973 if(not defined $VirtualTable_Model{2}{$ClassName}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010974 { # Removed_Virtual_Method, will be registered in mergeVirtualTables()
10975 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010976 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010977 if($VirtualTable_Model{2}{$ClassName}{$Symbol}-$VirtualTable_Model{1}{$ClassName}{$Symbol}==0)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010978 { # skip interfaces that have not changed the absolute virtual position
10979 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040010980 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010981 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
10982 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010983 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040010984 $VTableChanged_M{$BaseType{"Name"}} = 1;
10985 $VTableChanged_M{$ClassName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010986 foreach my $VirtFunc (keys(%{$AddedInt_Virt{$Level}{$BaseType{"Name"}}}))
10987 { # the reason of the layout change: added virtual functions
10988 next if($VirtualReplacement{$VirtFunc});
10989 my $ProblemType = "Added_Virtual_Method";
10990 if($CompleteSignature{2}{$VirtFunc}{"PureVirt"}) {
10991 $ProblemType = "Added_Pure_Virtual_Method";
10992 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040010993 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 2)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010994 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040010995 "Target"=>get_Signature($VirtFunc, 2) );
10996 }
10997 foreach my $VirtFunc (keys(%{$RemovedInt_Virt{$Level}{$BaseType{"Name"}}}))
10998 { # the reason of the layout change: removed virtual functions
10999 next if($VirtualReplacement{$VirtFunc});
11000 my $ProblemType = "Removed_Virtual_Method";
11001 if($CompleteSignature{1}{$VirtFunc}{"PureVirt"}) {
11002 $ProblemType = "Removed_Pure_Virtual_Method";
11003 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011004 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{get_Signature($VirtFunc, 1)}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011005 "Type_Name"=>$BaseType{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011006 "Target"=>get_Signature($VirtFunc, 1) );
11007 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011008 }
11009 }
11010 }
11011 }
11012 }
11013 }
11014 }
11015}
11016
11017sub isCreatable($$)
11018{
11019 my ($ClassId, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011020 if($AllocableClass{$LibVersion}{$TypeInfo{$LibVersion}{$ClassId}{"Name"}}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011021 or isCopyingClass($ClassId, $LibVersion)) {
11022 return 1;
11023 }
11024 if(keys(%{$Class_SubClasses{$LibVersion}{$ClassId}}))
11025 { # Fix for incomplete data: if this class has
11026 # a base class then it should also has a constructor
11027 return 1;
11028 }
11029 if($ReturnedClass{$LibVersion}{$ClassId})
11030 { # returned by some method of this class
11031 # or any other class
11032 return 1;
11033 }
11034 return 0;
11035}
11036
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011037sub isUsedClass($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011038{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011039 my ($ClassId, $LibVersion, $Level) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011040 if(keys(%{$ParamClass{$LibVersion}{$ClassId}}))
11041 { # parameter of some exported method
11042 return 1;
11043 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011044 my $CName = $TypeInfo{$LibVersion}{$ClassId}{"Name"};
11045 if(keys(%{$ClassMethods{$Level}{$LibVersion}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011046 { # method from target class
11047 return 1;
11048 }
11049 return 0;
11050}
11051
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011052sub mergeVirtualTables($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011053{ # check for changes in the virtual table
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011054 my ($Interface, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011055 # affected methods:
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011056 # - virtual
11057 # - pure-virtual
11058 # - non-virtual
11059 if($CompleteSignature{1}{$Interface}{"Data"})
11060 { # global data is not affected
11061 return;
11062 }
11063 my $Class_Id = $CompleteSignature{1}{$Interface}{"Class"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011064 if(not $Class_Id) {
11065 return;
11066 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011067 my $CName = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011068 if(cmpVTables_Real($CName, 1)==0)
11069 { # no changes
11070 return;
11071 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011072 $CheckedTypes{$Level}{$CName} = 1;
11073 if($Level eq "Binary")
11074 { # Binary-level
11075 if($CompleteSignature{1}{$Interface}{"PureVirt"}
11076 and not isUsedClass($Class_Id, 1, $Level))
11077 { # pure virtuals should not be affected
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011078 # if there are no exported methods using this class
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011079 return;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011080 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011081 }
11082 foreach my $Func (keys(%{$VirtualTable{1}{$CName}}))
11083 {
11084 if(defined $VirtualTable{2}{$CName}{$Func}
11085 and defined $CompleteSignature{2}{$Func})
11086 {
11087 if(not $CompleteSignature{1}{$Func}{"PureVirt"}
11088 and $CompleteSignature{2}{$Func}{"PureVirt"})
11089 { # became pure virtual
11090 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Pure"}{$tr_name{$Func}}}=(
11091 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011092 "Target"=>get_Signature_M($Func, 1) );
11093 $VTableChanged_M{$CName} = 1;
11094 }
11095 elsif($CompleteSignature{1}{$Func}{"PureVirt"}
11096 and not $CompleteSignature{2}{$Func}{"PureVirt"})
11097 { # became non-pure virtual
11098 %{$CompatProblems{$Level}{$Interface}{"Virtual_Method_Became_Non_Pure"}{$tr_name{$Func}}}=(
11099 "Type_Name"=>$CName,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011100 "Target"=>get_Signature_M($Func, 1) );
11101 $VTableChanged_M{$CName} = 1;
11102 }
11103 }
11104 }
11105 if($Level eq "Binary")
11106 { # Binary-level
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011107 # check virtual table structure
11108 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
11109 {
11110 next if($Interface eq $AddedVFunc);
11111 next if($VirtualReplacement{$AddedVFunc});
11112 my $VPos_Added = $VirtualTable{2}{$CName}{$AddedVFunc};
11113 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
11114 { # pure virtual methods affect all others (virtual and non-virtual)
11115 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011116 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011117 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011118 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011119 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011120 elsif(not defined $VirtualTable{1}{$CName}
11121 or $VPos_Added>keys(%{$VirtualTable{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011122 { # added virtual function at the end of v-table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011123 if(not keys(%{$VirtualTable_Model{1}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011124 { # became polymorphous class, added v-table pointer
11125 %{$CompatProblems{$Level}{$Interface}{"Added_First_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011126 "Type_Name"=>$CName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011127 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011128 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011129 }
11130 else
11131 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011132 my $VSize_Old = getVTable_Size($CName, 1);
11133 my $VSize_New = getVTable_Size($CName, 2);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011134 next if($VSize_Old==$VSize_New); # exception: register as removed and added virtual method
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011135 if(isCopyingClass($Class_Id, 1))
11136 { # class has no constructors and v-table will be copied by applications, this may affect all methods
11137 my $ProblemType = "Added_Virtual_Method";
11138 if(isLeafClass($Class_Id, 1)) {
11139 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Copying_Class";
11140 }
11141 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11142 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011143 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011144 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011145 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011146 else
11147 {
11148 my $ProblemType = "Added_Virtual_Method";
11149 if(isLeafClass($Class_Id, 1)) {
11150 $ProblemType = "Added_Virtual_Method_At_End_Of_Leaf_Allocable_Class";
11151 }
11152 %{$CompatProblems{$Level}{$Interface}{$ProblemType}{$tr_name{$AddedVFunc}}}=(
11153 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011154 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011155 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011156 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011157 }
11158 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011159 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11160 or $CompleteSignature{1}{$Interface}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011161 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011162 if(defined $VirtualTable{1}{$CName}
11163 and defined $VirtualTable{2}{$CName})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011164 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011165 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11166 my $VPos_New = $VirtualTable{2}{$CName}{$Interface};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011167
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011168 if($VPos_Added<=$VPos_Old and $VPos_Old!=$VPos_New)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011169 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011170 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11171 foreach my $ASymbol (@Affected)
11172 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011173 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11174 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011175 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011176 next;
11177 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011178 }
11179 $CheckedSymbols{$Level}{$ASymbol} = 1;
11180 %{$CompatProblems{$Level}{$ASymbol}{"Added_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11181 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011182 "Target"=>get_Signature($AddedVFunc, 2) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011183 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011184 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011185 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011186 }
11187 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011188 else {
11189 # safe
11190 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011191 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011192 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11193 {
11194 next if($VirtualReplacement{$RemovedVFunc});
11195 if($RemovedVFunc eq $Interface
11196 and $CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11197 { # This case is for removed virtual methods
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011198 # implemented in both versions of a library
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011199 next;
11200 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011201 if(not keys(%{$VirtualTable_Model{2}{$CName}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011202 { # became non-polymorphous class, removed v-table pointer
11203 %{$CompatProblems{$Level}{$Interface}{"Removed_Last_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11204 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011205 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011206 $VTableChanged_M{$CName} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011207 }
11208 elsif($CompleteSignature{1}{$Interface}{"Virt"}
11209 or $CompleteSignature{1}{$Interface}{"PureVirt"})
11210 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011211 if(defined $VirtualTable{1}{$CName} and defined $VirtualTable{2}{$CName})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011212 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011213 if(not defined $VirtualTable{1}{$CName}{$Interface}) {
11214 next;
11215 }
11216 my $VPos_New = -1;
11217 if(defined $VirtualTable{2}{$CName}{$Interface})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011218 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011219 $VPos_New = $VirtualTable{2}{$CName}{$Interface};
11220 }
11221 else
11222 {
11223 if($Interface ne $RemovedVFunc) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011224 next;
11225 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011226 }
11227 my $VPos_Removed = $VirtualTable{1}{$CName}{$RemovedVFunc};
11228 my $VPos_Old = $VirtualTable{1}{$CName}{$Interface};
11229 if($VPos_Removed<=$VPos_Old and $VPos_Old!=$VPos_New)
11230 {
11231 my @Affected = ($Interface, keys(%{$OverriddenMethods{1}{$Interface}}));
11232 foreach my $ASymbol (@Affected)
11233 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011234 if(not $CompleteSignature{1}{$ASymbol}{"PureVirt"})
11235 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011236 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011237 next;
11238 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011239 }
11240 my $ProblemType = "Removed_Virtual_Method";
11241 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"}) {
11242 $ProblemType = "Removed_Pure_Virtual_Method";
11243 }
11244 $CheckedSymbols{$Level}{$ASymbol} = 1;
11245 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$RemovedVFunc}}}=(
11246 "Type_Name"=>$CName,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011247 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011248 $VTableChanged_M{$TypeInfo{1}{$CompleteSignature{1}{$ASymbol}{"Class"}}{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011249 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011250 }
11251 }
11252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011253 }
11254 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011255 else
11256 { # Source-level
11257 foreach my $AddedVFunc (keys(%{$AddedInt_Virt{$Level}{$CName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011258 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011259 next if($Interface eq $AddedVFunc);
11260 if($CompleteSignature{2}{$AddedVFunc}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011261 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011262 %{$CompatProblems{$Level}{$Interface}{"Added_Pure_Virtual_Method"}{$tr_name{$AddedVFunc}}}=(
11263 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011264 "Target"=>get_Signature($AddedVFunc, 2) );
11265 }
11266 }
11267 foreach my $RemovedVFunc (keys(%{$RemovedInt_Virt{$Level}{$CName}}))
11268 {
11269 if($CompleteSignature{1}{$RemovedVFunc}{"PureVirt"})
11270 {
11271 %{$CompatProblems{$Level}{$Interface}{"Removed_Pure_Virtual_Method"}{$tr_name{$RemovedVFunc}}}=(
11272 "Type_Name"=>$CName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011273 "Target"=>get_Signature($RemovedVFunc, 1) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011274 }
11275 }
11276 }
11277}
11278
11279sub find_MemberPair_Pos_byName($$)
11280{
11281 my ($Member_Name, $Pair_Type) = @_;
11282 $Member_Name=~s/\A[_]+|[_]+\Z//g;
11283 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11284 {
11285 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos})
11286 {
11287 my $Name = $Pair_Type->{"Memb"}{$MemberPair_Pos}{"name"};
11288 $Name=~s/\A[_]+|[_]+\Z//g;
11289 if($Name eq $Member_Name) {
11290 return $MemberPair_Pos;
11291 }
11292 }
11293 }
11294 return "lost";
11295}
11296
11297sub find_MemberPair_Pos_byVal($$)
11298{
11299 my ($Member_Value, $Pair_Type) = @_;
11300 foreach my $MemberPair_Pos (sort {int($a)<=>int($b)} keys(%{$Pair_Type->{"Memb"}}))
11301 {
11302 if(defined $Pair_Type->{"Memb"}{$MemberPair_Pos}
11303 and $Pair_Type->{"Memb"}{$MemberPair_Pos}{"value"} eq $Member_Value) {
11304 return $MemberPair_Pos;
11305 }
11306 }
11307 return "lost";
11308}
11309
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011310my %Severity_Val=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011311 "High"=>3,
11312 "Medium"=>2,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011313 "Low"=>1,
11314 "Safe"=>-1
11315);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011316
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011317sub maxSeverity($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011318{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011319 my ($S1, $S2) = @_;
11320 if(cmpSeverities($S1, $S2)) {
11321 return $S1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011322 }
11323 else {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011324 return $S2;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011325 }
11326}
11327
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011328sub cmpSeverities($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011329{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011330 my ($S1, $S2) = @_;
11331 if(not $S1) {
11332 return 0;
11333 }
11334 elsif(not $S2) {
11335 return 1;
11336 }
11337 return ($Severity_Val{$S1}>$Severity_Val{$S2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011338}
11339
11340sub getProblemSeverity($$)
11341{
11342 my ($Level, $Kind) = @_;
11343 return $CompatRules{$Level}{$Kind}{"Severity"};
11344}
11345
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011346sub isRecurType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011347{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011348 foreach (@{$_[2]})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011349 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011350 if( $_->{"T1"} eq $_[0]
11351 and $_->{"T2"} eq $_[1] )
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011352 {
11353 return 1;
11354 }
11355 }
11356 return 0;
11357}
11358
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011359sub pushType($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011360{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011361 my %IDs = (
11362 "T1" => $_[0],
11363 "T2" => $_[1]
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011364 );
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011365 push(@{$_[2]}, \%IDs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011366}
11367
11368sub isRenamed($$$$$)
11369{
11370 my ($MemPos, $Type1, $LVersion1, $Type2, $LVersion2) = @_;
11371 my $Member_Name = $Type1->{"Memb"}{$MemPos}{"name"};
11372 my $MemberType_Id = $Type1->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011373 my %MemberType_Pure = get_PureType($MemberType_Id, $TypeInfo{$LVersion1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011374 if(not defined $Type2->{"Memb"}{$MemPos}) {
11375 return "";
11376 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011377 my $PairType_Id = $Type2->{"Memb"}{$MemPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011378 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{$LVersion2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011379
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011380 my $Pair_Name = $Type2->{"Memb"}{$MemPos}{"name"};
11381 my $MemberPair_Pos_Rev = ($Member_Name eq $Pair_Name)?$MemPos:find_MemberPair_Pos_byName($Pair_Name, $Type1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011382 if($MemberPair_Pos_Rev eq "lost")
11383 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011384 if($MemberType_Pure{"Name"} eq $PairType_Pure{"Name"})
11385 { # base type match
11386 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011387 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011388 if($TypeInfo{$LVersion1}{$MemberType_Id}{"Name"} eq $TypeInfo{$LVersion2}{$PairType_Id}{"Name"})
11389 { # exact type match
11390 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011391 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011392 if($MemberType_Pure{"Size"} eq $PairType_Pure{"Size"})
11393 { # size match
11394 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011395 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011396 if(isReserved($Pair_Name))
11397 { # reserved fields
11398 return $Pair_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011399 }
11400 }
11401 return "";
11402}
11403
11404sub isLastElem($$)
11405{
11406 my ($Pos, $TypeRef) = @_;
11407 my $Name = $TypeRef->{"Memb"}{$Pos}{"name"};
11408 if($Name=~/last|count|max|total/i)
11409 { # GST_LEVEL_COUNT, GST_RTSP_ELAST
11410 return 1;
11411 }
11412 elsif($Name=~/END|NLIMITS\Z/)
11413 { # __RLIMIT_NLIMITS
11414 return 1;
11415 }
11416 elsif($Name=~/\AN[A-Z](.+)[a-z]+s\Z/
11417 and $Pos+1==keys(%{$TypeRef->{"Memb"}}))
11418 { # NImageFormats, NColorRoles
11419 return 1;
11420 }
11421 return 0;
11422}
11423
11424sub nonComparable($$)
11425{
11426 my ($T1, $T2) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011427
11428 my $N1 = $T1->{"Name"};
11429 my $N2 = $T2->{"Name"};
11430
11431 $N1=~s/\A(struct|union|enum) //;
11432 $N2=~s/\A(struct|union|enum) //;
11433
11434 if($N1 ne $N2
11435 and not isAnon($N1)
11436 and not isAnon($N2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011437 { # different names
11438 if($T1->{"Type"} ne "Pointer"
11439 or $T2->{"Type"} ne "Pointer")
11440 { # compare base types
11441 return 1;
11442 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011443 if($N1!~/\Avoid\s*\*/
11444 and $N2=~/\Avoid\s*\*/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011445 {
11446 return 1;
11447 }
11448 }
11449 elsif($T1->{"Type"} ne $T2->{"Type"})
11450 { # different types
11451 if($T1->{"Type"} eq "Class"
11452 and $T2->{"Type"} eq "Struct")
11453 { # "class" to "struct"
11454 return 0;
11455 }
11456 elsif($T2->{"Type"} eq "Class"
11457 and $T1->{"Type"} eq "Struct")
11458 { # "struct" to "class"
11459 return 0;
11460 }
11461 else
11462 { # "class" to "enum"
11463 # "union" to "class"
11464 # ...
11465 return 1;
11466 }
11467 }
11468 return 0;
11469}
11470
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011471sub isOpaque($)
11472{
11473 my $T = $_[0];
11474 if(not defined $T->{"Memb"})
11475 {
11476 return 1;
11477 }
11478 return 0;
11479}
11480
11481sub removeVPtr($)
11482{ # support for old ABI dumps
11483 my $TPtr = $_[0];
11484 my @Pos = sort {int($a)<=>int($b)} keys(%{$TPtr->{"Memb"}});
11485 if($#Pos>=1)
11486 {
11487 foreach my $Pos (0 .. $#Pos-1)
11488 {
11489 %{$TPtr->{"Memb"}{$Pos}} = %{$TPtr->{"Memb"}{$Pos+1}};
11490 }
11491 delete($TPtr->{"Memb"}{$#Pos});
11492 }
11493}
11494
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011495sub mergeTypes($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011496{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011497 my ($Type1_Id, $Type2_Id, $Level) = @_;
11498 return () if(not $Type1_Id or not $Type2_Id);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011499 my (%Sub_SubProblems, %SubProblems) = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011500 if($Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011501 { # already merged
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011502 return %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011503 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011504 my %Type1 = get_Type($Type1_Id, 1);
11505 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040011506 if(not $Type1{"Name"} or not $Type2{"Name"}) {
11507 return ();
11508 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011509
11510 $CheckedTypes{$Level}{$Type1{"Name"}} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011511 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
11512 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011513 $CheckedTypes{$Level}{$Type1_Pure{"Name"}} = 1;
11514
11515 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
11516 {
11517 if($Type1_Pure{"Type"}=~/Struct|Union/
11518 and $Type2_Pure{"Type"}=~/Struct|Union/)
11519 {
11520 if(isOpaque(\%Type2_Pure) and not isOpaque(\%Type1_Pure))
11521 {
11522 %{$SubProblems{"Type_Became_Opaque"}{$Type1_Pure{"Name"}}}=(
11523 "Target"=>$Type1_Pure{"Name"},
11524 "Type_Name"=>$Type1_Pure{"Name"} );
11525
11526 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
11527 return %SubProblems;
11528 }
11529 }
11530 }
11531
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011532 if(not $Type1_Pure{"Size"}
11533 or not $Type2_Pure{"Size"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011534 { # including a case when "class Class { ... };" changed to "class Class;"
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040011535 if(not defined $Type1_Pure{"Memb"} or not defined $Type2_Pure{"Memb"}
11536 or index($Type1_Pure{"Name"}, "<")==-1 or index($Type2_Pure{"Name"}, "<")==-1)
11537 { # NOTE: template instances have no size
11538 return ();
11539 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011540 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011541 if(isRecurType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011542 { # skip recursive declarations
11543 return ();
11544 }
11545 return () if(not $Type1_Pure{"Name"} or not $Type2_Pure{"Name"});
11546 return () if($SkipTypes{1}{$Type1_Pure{"Name"}});
11547 return () if($SkipTypes{1}{$Type1{"Name"}});
11548
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011549 if($Type1_Pure{"Type"}=~/Class|Struct/ and $Type2_Pure{"Type"}=~/Class|Struct/)
11550 { # support for old ABI dumps
11551 # _vptr field added in 3.0
11552 if(not checkDump(1, "3.0") and checkDump(2, "3.0"))
11553 {
11554 if(defined $Type2_Pure{"Memb"}
11555 and $Type2_Pure{"Memb"}{0}{"name"} eq "_vptr")
11556 {
11557 if(keys(%{$Type2_Pure{"Memb"}})==1) {
11558 delete($Type2_Pure{"Memb"}{0});
11559 }
11560 else {
11561 removeVPtr(\%Type2_Pure);
11562 }
11563 }
11564 }
11565 if(checkDump(1, "3.0") and not checkDump(2, "3.0"))
11566 {
11567 if(defined $Type1_Pure{"Memb"}
11568 and $Type1_Pure{"Memb"}{0}{"name"} eq "_vptr")
11569 {
11570 if(keys(%{$Type1_Pure{"Memb"}})==1) {
11571 delete($Type1_Pure{"Memb"}{0});
11572 }
11573 else {
11574 removeVPtr(\%Type1_Pure);
11575 }
11576 }
11577 }
11578 }
11579
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011580 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
11581 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011582
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040011583 if(not $UseOldDumps and %Typedef_1 and %Typedef_2
11584 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef"
11585 and $Typedef_1{"Name"} eq $Typedef_2{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011586 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040011587 my %Base_1 = get_OneStep_BaseType($Typedef_1{"Tid"}, $TypeInfo{1});
11588 my %Base_2 = get_OneStep_BaseType($Typedef_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011589 if($Base_1{"Name"} ne $Base_2{"Name"})
11590 {
11591 if(differentDumps("G")
11592 or differentDumps("V"))
11593 { # different GCC versions or different dumps
11594 $Base_1{"Name"} = uncover_typedefs($Base_1{"Name"}, 1);
11595 $Base_2{"Name"} = uncover_typedefs($Base_2{"Name"}, 2);
11596 # std::__va_list and __va_list
11597 $Base_1{"Name"}=~s/\A(\w+::)+//;
11598 $Base_2{"Name"}=~s/\A(\w+::)+//;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011599 $Base_1{"Name"} = formatName($Base_1{"Name"}, "T");
11600 $Base_2{"Name"} = formatName($Base_2{"Name"}, "T");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040011601 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011602 }
11603 if($Base_1{"Name"}!~/anon\-/ and $Base_2{"Name"}!~/anon\-/
11604 and $Base_1{"Name"} ne $Base_2{"Name"})
11605 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011606 if($Level eq "Binary"
11607 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011608 {
11609 %{$SubProblems{"DataType_Size"}{$Typedef_1{"Name"}}}=(
11610 "Target"=>$Typedef_1{"Name"},
11611 "Type_Name"=>$Typedef_1{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011612 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
11613 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE );
11614 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011615 my %Base1_Pure = get_PureType($Base_1{"Tid"}, $TypeInfo{1});
11616 my %Base2_Pure = get_PureType($Base_2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011617 if(tNameLock($Base_1{"Tid"}, $Base_2{"Tid"}))
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011618 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011619 if(diffTypes($Base1_Pure{"Tid"}, $Base2_Pure{"Tid"}, $Level))
11620 {
11621 %{$SubProblems{"Typedef_BaseType_Format"}{$Typedef_1{"Name"}}}=(
11622 "Target"=>$Typedef_1{"Name"},
11623 "Type_Name"=>$Typedef_1{"Name"},
11624 "Old_Value"=>$Base_1{"Name"},
11625 "New_Value"=>$Base_2{"Name"} );
11626 }
11627 else
11628 {
11629 %{$SubProblems{"Typedef_BaseType"}{$Typedef_1{"Name"}}}=(
11630 "Target"=>$Typedef_1{"Name"},
11631 "Type_Name"=>$Typedef_1{"Name"},
11632 "Old_Value"=>$Base_1{"Name"},
11633 "New_Value"=>$Base_2{"Name"} );
11634 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011635 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011636 }
11637 }
11638 if(nonComparable(\%Type1_Pure, \%Type2_Pure))
11639 { # different types (reported in detectTypeChange(...))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011640 my $TT1 = $Type1_Pure{"Type"};
11641 my $TT2 = $Type2_Pure{"Type"};
11642
11643 if($TT1 ne $TT2
11644 and $TT1!~/Intrinsic|Pointer|Ref|Typedef/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011645 { # different type of the type
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011646 my $Short1 = $Type1_Pure{"Name"};
11647 my $Short2 = $Type2_Pure{"Name"};
11648
11649 $Short1=~s/\A\Q$TT1\E //ig;
11650 $Short2=~s/\A\Q$TT2\E //ig;
11651
11652 if($Short1 eq $Short2)
11653 {
11654 %{$SubProblems{"DataType_Type"}{$Type1_Pure{"Name"}}}=(
11655 "Target"=>$Type1_Pure{"Name"},
11656 "Type_Name"=>$Type1_Pure{"Name"},
11657 "Old_Value"=>lc($Type1_Pure{"Type"}),
11658 "New_Value"=>lc($Type2_Pure{"Type"}) );
11659 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011660 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011661 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011662 return %SubProblems;
11663 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011664 pushType($Type1_Pure{"Tid"}, $Type2_Pure{"Tid"}, \@RecurTypes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011665 if(($Type1_Pure{"Name"} eq $Type2_Pure{"Name"}
11666 or (isAnon($Type1_Pure{"Name"}) and isAnon($Type2_Pure{"Name"})))
11667 and $Type1_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11668 { # checking size
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011669 if($Level eq "Binary"
11670 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011671 {
11672 my $ProblemKind = "DataType_Size";
11673 if($Type1_Pure{"Type"} eq "Class"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011674 and keys(%{$ClassMethods{$Level}{1}{$Type1_Pure{"Name"}}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011675 {
11676 if(isCopyingClass($Type1_Pure{"Tid"}, 1)) {
11677 $ProblemKind = "Size_Of_Copying_Class";
11678 }
11679 elsif($AllocableClass{1}{$Type1_Pure{"Name"}})
11680 {
11681 if(int($Type2_Pure{"Size"})>int($Type1_Pure{"Size"})) {
11682 $ProblemKind = "Size_Of_Allocable_Class_Increased";
11683 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011684 else
11685 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011686 # descreased size of allocable class
11687 # it has no special effects
11688 }
11689 }
11690 }
11691 %{$SubProblems{$ProblemKind}{$Type1_Pure{"Name"}}}=(
11692 "Target"=>$Type1_Pure{"Name"},
11693 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011694 "Old_Size"=>$Type1_Pure{"Size"}*$BYTE_SIZE,
11695 "New_Size"=>$Type2_Pure{"Size"}*$BYTE_SIZE,
11696 "InitialType_Type"=>$Type1_Pure{"Type"} );
11697 }
11698 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011699 if(defined $Type1_Pure{"BaseType"}
11700 and defined $Type2_Pure{"BaseType"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040011701 { # checking base types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011702 %Sub_SubProblems = mergeTypes($Type1_Pure{"BaseType"}, $Type2_Pure{"BaseType"}, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011703 foreach my $Sub_SubProblemType (keys(%Sub_SubProblems))
11704 {
11705 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems{$Sub_SubProblemType}}))
11706 {
11707 foreach my $Attr (keys(%{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}})) {
11708 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr} = $Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr};
11709 }
11710 $SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{"InitialType_Type"} = $Type1_Pure{"Type"};
11711 }
11712 }
11713 }
11714 my (%AddedField, %RemovedField, %RenamedField, %RenamedField_Rev, %RelatedField, %RelatedField_Rev) = ();
11715 my %NameToPosA = map {$Type1_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type1_Pure{"Memb"}});
11716 my %NameToPosB = map {$Type2_Pure{"Memb"}{$_}{"name"}=>$_} keys(%{$Type2_Pure{"Memb"}});
11717 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11718 { # detect removed and renamed fields
11719 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11720 next if(not $Member_Name);
11721 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);
11722 if($MemberPair_Pos eq "lost")
11723 {
11724 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11725 {
11726 if(isUnnamed($Member_Name))
11727 { # support for old-version dumps
11728 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011729 if(not checkDump(2, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011730 next;
11731 }
11732 }
11733 if(my $RenamedTo = isRenamed($Member_Pos, \%Type1_Pure, 1, \%Type2_Pure, 2))
11734 { # renamed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011735 $RenamedField{$Member_Pos} = $RenamedTo;
11736 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011737 }
11738 else
11739 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011740 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011741 }
11742 }
11743 elsif($Type1_Pure{"Type"} eq "Enum")
11744 {
11745 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11746 next if($Member_Value1 eq "");
11747 $MemberPair_Pos = find_MemberPair_Pos_byVal($Member_Value1, \%Type2_Pure);
11748 if($MemberPair_Pos ne "lost")
11749 { # renamed
11750 my $RenamedTo = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"name"};
11751 my $MemberPair_Pos_Rev = find_MemberPair_Pos_byName($RenamedTo, \%Type1_Pure);
11752 if($MemberPair_Pos_Rev eq "lost")
11753 {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011754 $RenamedField{$Member_Pos} = $RenamedTo;
11755 $RenamedField_Rev{$NameToPosB{$RenamedTo}} = $Member_Name;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011756 }
11757 else {
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011758 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011759 }
11760 }
11761 else
11762 { # removed
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011763 $RemovedField{$Member_Pos} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011764 }
11765 }
11766 }
11767 else
11768 { # related
11769 $RelatedField{$Member_Pos} = $MemberPair_Pos;
11770 $RelatedField_Rev{$MemberPair_Pos} = $Member_Pos;
11771 }
11772 }
11773 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11774 { # detect added fields
11775 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11776 next if(not $Member_Name);
11777 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);
11778 if($MemberPair_Pos eq "lost")
11779 {
11780 if(isUnnamed($Member_Name))
11781 { # support for old-version dumps
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011782 # unnamed fields have been introduced in the ACC 1.23 (dump 2.1 format)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011783 if(not checkDump(1, "2.1")) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011784 next;
11785 }
11786 }
11787 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union|Enum)\Z/)
11788 {
11789 if(not $RenamedField_Rev{$Member_Pos})
11790 { # added
11791 $AddedField{$Member_Pos}=1;
11792 }
11793 }
11794 }
11795 }
11796 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11797 { # detect moved fields
11798 my (%RelPos, %RelPosName, %AbsPos) = ();
11799 my $Pos = 0;
11800 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
11801 { # relative positions in 1st version
11802 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11803 next if(not $Member_Name);
11804 if(not $RemovedField{$Member_Pos})
11805 { # old type without removed fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011806 $RelPos{1}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011807 $RelPosName{1}{$Pos} = $Member_Name;
11808 $AbsPos{1}{$Pos++} = $Member_Pos;
11809 }
11810 }
11811 $Pos = 0;
11812 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
11813 { # relative positions in 2nd version
11814 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
11815 next if(not $Member_Name);
11816 if(not $AddedField{$Member_Pos})
11817 { # new type without added fields
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011818 $RelPos{2}{$Member_Name} = $Pos;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011819 $RelPosName{2}{$Pos} = $Member_Name;
11820 $AbsPos{2}{$Pos++} = $Member_Pos;
11821 }
11822 }
11823 foreach my $Member_Name (keys(%{$RelPos{1}}))
11824 {
11825 my $RPos1 = $RelPos{1}{$Member_Name};
11826 my $AbsPos1 = $NameToPosA{$Member_Name};
11827 my $Member_Name2 = $Member_Name;
11828 if(my $RenamedTo = $RenamedField{$AbsPos1})
11829 { # renamed
11830 $Member_Name2 = $RenamedTo;
11831 }
11832 my $RPos2 = $RelPos{2}{$Member_Name2};
11833 if($RPos2 ne "" and $RPos1 ne $RPos2)
11834 { # different relative positions
11835 my $AbsPos2 = $NameToPosB{$Member_Name2};
11836 if($AbsPos1 ne $AbsPos2)
11837 { # different absolute positions
11838 my $ProblemType = "Moved_Field";
11839 if(not isPublic(\%Type1_Pure, $AbsPos1))
11840 { # may change layout and size of type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011841 if($Level eq "Source") {
11842 next;
11843 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011844 $ProblemType = "Moved_Private_Field";
11845 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011846 if($Level eq "Binary"
11847 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011848 { # affected size
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011849 my $MemSize1 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$AbsPos1}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011850 my $MovedAbsPos = $AbsPos{1}{$RPos2};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040011851 my $MemSize2 = $TypeInfo{1}{$Type1_Pure{"Memb"}{$MovedAbsPos}{"type"}}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011852 if($MemSize1 ne $MemSize2) {
11853 $ProblemType .= "_And_Size";
11854 }
11855 }
11856 if($ProblemType eq "Moved_Private_Field") {
11857 next;
11858 }
11859 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11860 "Target"=>$Member_Name,
11861 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011862 "Old_Value"=>$RPos1,
11863 "New_Value"=>$RPos2 );
11864 }
11865 }
11866 }
11867 }
11868 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type1_Pure{"Memb"}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011869 { # check older fields, public and private
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011870 my $Member_Name = $Type1_Pure{"Memb"}{$Member_Pos}{"name"};
11871 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040011872 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011873 if(my $RenamedTo = $RenamedField{$Member_Pos})
11874 { # renamed
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040011875 if(defined $Constants{2}{$Member_Name})
11876 {
11877 if($Constants{2}{$Member_Name}{"Value"} eq $RenamedTo)
11878 { # define OLD NEW
11879 next; # Safe
11880 }
11881 }
11882
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011883 if($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11884 {
11885 if(isPublic(\%Type1_Pure, $Member_Pos))
11886 {
11887 %{$SubProblems{"Renamed_Field"}{$Member_Name}}=(
11888 "Target"=>$Member_Name,
11889 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011890 "Old_Value"=>$Member_Name,
11891 "New_Value"=>$RenamedTo );
11892 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011893 elsif(isReserved($Member_Name))
11894 {
11895 %{$SubProblems{"Used_Reserved_Field"}{$Member_Name}}=(
11896 "Target"=>$Member_Name,
11897 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040011898 "Old_Value"=>$Member_Name,
11899 "New_Value"=>$RenamedTo );
11900 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011901 }
11902 elsif($Type1_Pure{"Type"} eq "Enum")
11903 {
11904 %{$SubProblems{"Enum_Member_Name"}{$Type1_Pure{"Memb"}{$Member_Pos}{"value"}}}=(
11905 "Target"=>$Type1_Pure{"Memb"}{$Member_Pos}{"value"},
11906 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011907 "Old_Value"=>$Member_Name,
11908 "New_Value"=>$RenamedTo );
11909 }
11910 }
11911 elsif($RemovedField{$Member_Pos})
11912 { # removed
11913 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
11914 {
11915 my $ProblemType = "Removed_Field";
11916 if(not isPublic(\%Type1_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011917 or isUnnamed($Member_Name))
11918 {
11919 if($Level eq "Source") {
11920 next;
11921 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011922 $ProblemType = "Removed_Private_Field";
11923 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011924 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011925 and not isMemPadded($Member_Pos, -1, \%Type1_Pure, \%RemovedField, $TypeInfo{1}, getArch(1), $WORD_SIZE{1}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011926 {
11927 if(my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
11928 { # affected fields
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011929 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 +040011930 { # changed offset
11931 $ProblemType .= "_And_Layout";
11932 }
11933 }
11934 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
11935 { # affected size
11936 $ProblemType .= "_And_Size";
11937 }
11938 }
11939 if($ProblemType eq "Removed_Private_Field") {
11940 next;
11941 }
11942 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11943 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011944 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011945 }
11946 elsif($Type2_Pure{"Type"} eq "Union")
11947 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040011948 if($Level eq "Binary"
11949 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011950 {
11951 %{$SubProblems{"Removed_Union_Field_And_Size"}{$Member_Name}}=(
11952 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011953 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011954 }
11955 else
11956 {
11957 %{$SubProblems{"Removed_Union_Field"}{$Member_Name}}=(
11958 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040011959 "Type_Name"=>$Type1_Pure{"Name"} );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011960 }
11961 }
11962 elsif($Type1_Pure{"Type"} eq "Enum")
11963 {
11964 %{$SubProblems{"Enum_Member_Removed"}{$Member_Name}}=(
11965 "Target"=>$Member_Name,
11966 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011967 "Old_Value"=>$Member_Name );
11968 }
11969 }
11970 else
11971 { # changed
11972 my $MemberPair_Pos = $RelatedField{$Member_Pos};
11973 if($Type1_Pure{"Type"} eq "Enum")
11974 {
11975 my $Member_Value1 = $Type1_Pure{"Memb"}{$Member_Pos}{"value"};
11976 next if($Member_Value1 eq "");
11977 my $Member_Value2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"value"};
11978 next if($Member_Value2 eq "");
11979 if($Member_Value1 ne $Member_Value2)
11980 {
11981 my $ProblemType = "Enum_Member_Value";
11982 if(isLastElem($Member_Pos, \%Type1_Pure)) {
11983 $ProblemType = "Enum_Last_Member_Value";
11984 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011985 if($SkipConstants{1}{$Member_Name}) {
11986 $ProblemType = "Enum_Private_Member_Value";
11987 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011988 %{$SubProblems{$ProblemType}{$Member_Name}}=(
11989 "Target"=>$Member_Name,
11990 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040011991 "Old_Value"=>$Member_Value1,
11992 "New_Value"=>$Member_Value2 );
11993 }
11994 }
11995 elsif($Type2_Pure{"Type"}=~/\A(Struct|Class|Union)\Z/)
11996 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040011997 my $Access1 = $Type1_Pure{"Memb"}{$Member_Pos}{"access"};
11998 my $Access2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"access"};
11999
12000 if($Access1 ne "private"
12001 and $Access2 eq "private")
12002 {
12003 %{$SubProblems{"Field_Became_Private"}{$Member_Name}}=(
12004 "Target"=>$Member_Name,
12005 "Type_Name"=>$Type1_Pure{"Name"});
12006 }
12007 elsif($Access1 ne "protected"
12008 and $Access1 ne "private"
12009 and $Access2 eq "protected")
12010 {
12011 %{$SubProblems{"Field_Became_Protected"}{$Member_Name}}=(
12012 "Target"=>$Member_Name,
12013 "Type_Name"=>$Type1_Pure{"Name"});
12014 }
12015
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012016 my $MemberType1_Id = $Type1_Pure{"Memb"}{$Member_Pos}{"type"};
12017 my $MemberType2_Id = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012018 my $SizeV1 = $TypeInfo{1}{$MemberType1_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012019 if(my $BSize1 = $Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}) {
12020 $SizeV1 = $BSize1;
12021 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012022 my $SizeV2 = $TypeInfo{2}{$MemberType2_Id}{"Size"}*$BYTE_SIZE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012023 if(my $BSize2 = $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}) {
12024 $SizeV2 = $BSize2;
12025 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012026 my $MemberType1_Name = $TypeInfo{1}{$MemberType1_Id}{"Name"};
12027 my $MemberType2_Name = $TypeInfo{2}{$MemberType2_Id}{"Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012028 if($Level eq "Binary"
12029 and $SizeV1 ne $SizeV2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012030 {
12031 if($MemberType1_Name eq $MemberType2_Name or (isAnon($MemberType1_Name) and isAnon($MemberType2_Name))
12032 or ($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"} and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"}))
12033 { # field size change (including anon-structures and unions)
12034 # - same types
12035 # - unnamed types
12036 # - bitfields
12037 my $ProblemType = "Field_Size";
12038 if(not isPublic(\%Type1_Pure, $Member_Pos)
12039 or isUnnamed($Member_Name))
12040 { # should not be accessed by applications, goes to "Low Severity"
12041 # example: "abidata" members in GStreamer types
12042 $ProblemType = "Private_".$ProblemType;
12043 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012044 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 +040012045 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012046 if($Type2_Pure{"Type"} ne "Union"
12047 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012048 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012049 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 +040012050 { # changed offset
12051 $ProblemType .= "_And_Layout";
12052 }
12053 }
12054 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12055 $ProblemType .= "_And_Type_Size";
12056 }
12057 }
12058 if($ProblemType eq "Private_Field_Size")
12059 { # private field size with no effect
12060 $ProblemType = "";
12061 }
Andrey Ponomarenko46bef512013-06-14 16:33:03 +040012062 if($ProblemType eq "Field_Size")
12063 {
12064 if($Type1_Pure{"Type"}=~/Union|Struct/ and $SizeV1<$SizeV2)
12065 { # Low severity
12066 $ProblemType = "Struct_Field_Size_Increased";
12067 }
12068 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012069 if($ProblemType)
12070 { # register a problem
12071 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12072 "Target"=>$Member_Name,
12073 "Type_Name"=>$Type1_Pure{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012074 "Old_Size"=>$SizeV1,
12075 "New_Size"=>$SizeV2);
12076 }
12077 }
12078 }
12079 if($Type1_Pure{"Memb"}{$Member_Pos}{"bitfield"}
12080 or $Type2_Pure{"Memb"}{$MemberPair_Pos}{"bitfield"})
12081 { # do NOT check bitfield type changes
12082 next;
12083 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012084 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012085 {
12086 if(not $Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12087 and $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12088 {
12089 %{$SubProblems{"Field_Became_Mutable"}{$Member_Name}}=(
12090 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012091 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012092 }
12093 elsif($Type1_Pure{"Memb"}{$Member_Pos}{"mutable"}
12094 and not $Type2_Pure{"Memb"}{$MemberPair_Pos}{"mutable"})
12095 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012096 %{$SubProblems{"Field_Became_Non_Mutable"}{$Member_Name}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012097 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012098 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012099 }
12100 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012101 %Sub_SubProblems = detectTypeChange($MemberType1_Id, $MemberType2_Id, "Field", $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012102 foreach my $ProblemType (keys(%Sub_SubProblems))
12103 {
12104 my $Old_Value = $Sub_SubProblems{$ProblemType}{"Old_Value"};
12105 my $New_Value = $Sub_SubProblems{$ProblemType}{"New_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012106
12107 # quals
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012108 if($ProblemType eq "Field_Type"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012109 or $ProblemType eq "Field_Type_And_Size"
12110 or $ProblemType eq "Field_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012111 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012112 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012113 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012114 if(addedQual($Old_Value, $New_Value, "volatile")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012115 %{$Sub_SubProblems{"Field_Became_Volatile"}} = %{$Sub_SubProblems{$ProblemType}};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012116 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012117 elsif(removedQual($Old_Value, $New_Value, "volatile")) {
12118 %{$Sub_SubProblems{"Field_Became_Non_Volatile"}} = %{$Sub_SubProblems{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012119 }
12120 }
12121 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
12122 {
12123 if($RA==2) {
12124 %{$Sub_SubProblems{"Field_Added_Const"}} = %{$Sub_SubProblems{$ProblemType}};
12125 }
12126 else {
12127 %{$Sub_SubProblems{"Field_Became_Const"}} = %{$Sub_SubProblems{$ProblemType}};
12128 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012129 }
12130 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
12131 {
12132 if($RR==2) {
12133 %{$Sub_SubProblems{"Field_Removed_Const"}} = %{$Sub_SubProblems{$ProblemType}};
12134 }
12135 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012136 %{$Sub_SubProblems{"Field_Became_Non_Const"}} = %{$Sub_SubProblems{$ProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012137 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012138 }
12139 }
12140 }
12141
12142 if($Level eq "Source")
12143 {
12144 foreach my $ProblemType (keys(%Sub_SubProblems))
12145 {
12146 my $Old_Value = $Sub_SubProblems{$ProblemType}{"Old_Value"};
12147 my $New_Value = $Sub_SubProblems{$ProblemType}{"New_Value"};
12148
12149 if($ProblemType eq "Field_Type")
12150 {
12151 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012152 delete($Sub_SubProblems{$ProblemType});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012153 }
12154 }
12155 }
12156 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012157
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012158 foreach my $ProblemType (keys(%Sub_SubProblems))
12159 {
12160 my $ProblemType_Init = $ProblemType;
12161 if($ProblemType eq "Field_Type_And_Size")
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012162 { # Binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012163 if(not isPublic(\%Type1_Pure, $Member_Pos)
12164 or isUnnamed($Member_Name)) {
12165 $ProblemType = "Private_".$ProblemType;
12166 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012167 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 +040012168 { # check an effect
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012169 if($Type2_Pure{"Type"} ne "Union"
12170 and my $MNum = isAccessible(\%Type1_Pure, \%RemovedField, $Member_Pos+1, -1))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012171 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012172 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 +040012173 { # changed offset
12174 $ProblemType .= "_And_Layout";
12175 }
12176 }
12177 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12178 $ProblemType .= "_And_Type_Size";
12179 }
12180 }
12181 }
12182 else
12183 {
12184 if(not isPublic(\%Type1_Pure, $Member_Pos)
12185 or isUnnamed($Member_Name)) {
12186 next;
12187 }
12188 }
12189 if($ProblemType eq "Private_Field_Type_And_Size")
12190 { # private field change with no effect
12191 next;
12192 }
12193 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12194 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012195 "Type_Name"=>$Type1_Pure{"Name"});
12196
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012197 foreach my $Attr (keys(%{$Sub_SubProblems{$ProblemType_Init}}))
12198 { # other properties
12199 $SubProblems{$ProblemType}{$Member_Name}{$Attr} = $Sub_SubProblems{$ProblemType_Init}{$Attr};
12200 }
12201 }
12202 if(not isPublic(\%Type1_Pure, $Member_Pos))
12203 { # do NOT check internal type changes
12204 next;
12205 }
12206 if($MemberType1_Id and $MemberType2_Id)
12207 {# checking member type changes (replace)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012208 %Sub_SubProblems = mergeTypes($MemberType1_Id, $MemberType2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012209 foreach my $Sub_SubProblemType (keys(%Sub_SubProblems))
12210 {
12211 foreach my $Sub_SubLocation (keys(%{$Sub_SubProblems{$Sub_SubProblemType}}))
12212 {
12213 my $NewLocation = ($Sub_SubLocation)?$Member_Name."->".$Sub_SubLocation:$Member_Name;
12214 $SubProblems{$Sub_SubProblemType}{$NewLocation}{"IsInTypeInternals"}=1;
12215 foreach my $Attr (keys(%{$Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}})) {
12216 $SubProblems{$Sub_SubProblemType}{$NewLocation}{$Attr} = $Sub_SubProblems{$Sub_SubProblemType}{$Sub_SubLocation}{$Attr};
12217 }
12218 if($Sub_SubLocation!~/\-\>/) {
12219 $SubProblems{$Sub_SubProblemType}{$NewLocation}{"Start_Type_Name"} = $MemberType1_Name;
12220 }
12221 }
12222 }
12223 }
12224 }
12225 }
12226 }
12227 foreach my $Member_Pos (sort {int($a) <=> int($b)} keys(%{$Type2_Pure{"Memb"}}))
12228 { # checking added members, public and private
12229 my $Member_Name = $Type2_Pure{"Memb"}{$Member_Pos}{"name"};
12230 next if(not $Member_Name);
Andrey Ponomarenko082b4d02013-06-28 17:42:57 +040012231 next if($Member_Name eq "_vptr");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012232 if($AddedField{$Member_Pos})
12233 { # added
12234 if($Type2_Pure{"Type"}=~/\A(Struct|Class)\Z/)
12235 {
12236 my $ProblemType = "Added_Field";
12237 if(not isPublic(\%Type2_Pure, $Member_Pos)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012238 or isUnnamed($Member_Name))
12239 {
12240 if($Level eq "Source") {
12241 next;
12242 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012243 $ProblemType = "Added_Private_Field";
12244 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012245 if($Level eq "Binary"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012246 and not isMemPadded($Member_Pos, -1, \%Type2_Pure, \%AddedField, $TypeInfo{2}, getArch(2), $WORD_SIZE{2}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012247 {
12248 if(my $MNum = isAccessible(\%Type2_Pure, \%AddedField, $Member_Pos, -1))
12249 { # public fields after the current
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012250 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 +040012251 { # changed offset
12252 $ProblemType .= "_And_Layout";
12253 }
12254 }
12255 if($Type1_Pure{"Size"} ne $Type2_Pure{"Size"}) {
12256 $ProblemType .= "_And_Size";
12257 }
12258 }
12259 if($ProblemType eq "Added_Private_Field")
12260 { # skip added private fields
12261 next;
12262 }
12263 %{$SubProblems{$ProblemType}{$Member_Name}}=(
12264 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012265 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012266 }
12267 elsif($Type2_Pure{"Type"} eq "Union")
12268 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012269 if($Level eq "Binary"
12270 and $Type1_Pure{"Size"} ne $Type2_Pure{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012271 {
12272 %{$SubProblems{"Added_Union_Field_And_Size"}{$Member_Name}}=(
12273 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012274 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012275 }
12276 else
12277 {
12278 %{$SubProblems{"Added_Union_Field"}{$Member_Name}}=(
12279 "Target"=>$Member_Name,
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012280 "Type_Name"=>$Type1_Pure{"Name"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012281 }
12282 }
12283 elsif($Type2_Pure{"Type"} eq "Enum")
12284 {
12285 my $Member_Value = $Type2_Pure{"Memb"}{$Member_Pos}{"value"};
12286 next if($Member_Value eq "");
12287 %{$SubProblems{"Added_Enum_Member"}{$Member_Name}}=(
12288 "Target"=>$Member_Name,
12289 "Type_Name"=>$Type2_Pure{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012290 "New_Value"=>$Member_Value);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012291 }
12292 }
12293 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012294 %{$Cache{"mergeTypes"}{$Level}{$Type1_Id}{$Type2_Id}} = %SubProblems;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012295 pop(@RecurTypes);
12296 return %SubProblems;
12297}
12298
12299sub isUnnamed($) {
12300 return $_[0]=~/\Aunnamed\d+\Z/;
12301}
12302
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012303sub get_ShortClass($$)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012304{
12305 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012306 my $TypeName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
12307 if($TypeInfo{$LibVersion}{$TypeId}{"Type"}!~/Intrinsic|Class|Struct|Union|Enum/) {
12308 $TypeName = uncover_typedefs($TypeName, $LibVersion);
12309 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012310 if(my $NameSpace = $TypeInfo{$LibVersion}{$TypeId}{"NameSpace"}) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040012311 $TypeName=~s/\A(struct |)\Q$NameSpace\E\:\://g;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012312 }
12313 return $TypeName;
12314}
12315
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012316sub goToFirst($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012317{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012318 my ($TypeId, $LibVersion, $Type_Type) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012319 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012320 if(defined $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}) {
12321 return %{$Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012322 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012323 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12324 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012325 return () if(not $Type{"Type"});
12326 if($Type{"Type"} ne $Type_Type)
12327 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012328 return () if(not $Type{"BaseType"});
12329 %Type = goToFirst($Type{"BaseType"}, $LibVersion, $Type_Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012330 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012331 $Cache{"goToFirst"}{$TypeId}{$LibVersion}{$Type_Type} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012332 return %Type;
12333}
12334
12335my %TypeSpecAttributes = (
12336 "Const" => 1,
12337 "Volatile" => 1,
12338 "ConstVolatile" => 1,
12339 "Restrict" => 1,
12340 "Typedef" => 1
12341);
12342
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012343sub get_PureType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012344{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012345 my ($TypeId, $Info) = @_;
12346 if(not $TypeId or not $Info
12347 or not $Info->{$TypeId}) {
12348 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012349 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012350 if(defined $Cache{"get_PureType"}{$TypeId}{$Info}) {
12351 return %{$Cache{"get_PureType"}{$TypeId}{$Info}};
12352 }
12353 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012354 return %Type if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012355 if($TypeSpecAttributes{$Type{"Type"}}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012356 %Type = get_PureType($Type{"BaseType"}, $Info);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012357 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012358 $Cache{"get_PureType"}{$TypeId}{$Info} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012359 return %Type;
12360}
12361
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012362sub get_PLevel($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012363{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012364 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012365 return 0 if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012366 if(defined $Cache{"get_PLevel"}{$TypeId}{$LibVersion}) {
12367 return $Cache{"get_PLevel"}{$TypeId}{$LibVersion};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012368 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012369 return 0 if(not $TypeInfo{$LibVersion}{$TypeId});
12370 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012371 return 1 if($Type{"Type"}=~/FuncPtr|FieldPtr/);
12372 my $PLevel = 0;
12373 if($Type{"Type"} =~/Pointer|Ref|FuncPtr|FieldPtr/) {
12374 $PLevel += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012375 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012376 return $PLevel if(not $Type{"BaseType"});
12377 $PLevel += get_PLevel($Type{"BaseType"}, $LibVersion);
12378 $Cache{"get_PLevel"}{$TypeId}{$LibVersion} = $PLevel;
12379 return $PLevel;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012380}
12381
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012382sub get_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012383{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012384 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012385 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012386 if(defined $Cache{"get_BaseType"}{$TypeId}{$LibVersion}) {
12387 return %{$Cache{"get_BaseType"}{$TypeId}{$LibVersion}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012388 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012389 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12390 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012391 return %Type if(not $Type{"BaseType"});
12392 %Type = get_BaseType($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012393 $Cache{"get_BaseType"}{$TypeId}{$LibVersion} = \%Type;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012394 return %Type;
12395}
12396
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012397sub get_BaseTypeQual($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012398{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012399 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012400 return "" if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012401 return "" if(not $TypeInfo{$LibVersion}{$TypeId});
12402 my %Type = %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012403 return "" if(not $Type{"BaseType"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012404 my $Qual = "";
12405 if($Type{"Type"} eq "Pointer") {
12406 $Qual .= "*";
12407 }
12408 elsif($Type{"Type"} eq "Ref") {
12409 $Qual .= "&";
12410 }
12411 elsif($Type{"Type"} eq "ConstVolatile") {
12412 $Qual .= "const volatile";
12413 }
12414 elsif($Type{"Type"} eq "Const"
12415 or $Type{"Type"} eq "Volatile"
12416 or $Type{"Type"} eq "Restrict") {
12417 $Qual .= lc($Type{"Type"});
12418 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012419 my $BQual = get_BaseTypeQual($Type{"BaseType"}, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012420 return $BQual.$Qual;
12421}
12422
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012423sub get_OneStep_BaseType($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012424{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012425 my ($TypeId, $Info) = @_;
12426 if(not $TypeId or not $Info
12427 or not $Info->{$TypeId}) {
12428 return ();
12429 }
12430 my %Type = %{$Info->{$TypeId}};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012431 return %Type if(not $Type{"BaseType"});
12432 if(my $BTid = $Type{"BaseType"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040012433 {
12434 if($Info->{$BTid}) {
12435 return %{$Info->{$BTid}};
12436 }
12437 else { # something is going wrong
12438 return ();
12439 }
12440 }
12441 else {
12442 return %Type;
12443 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012444}
12445
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012446sub get_Type($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012447{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012448 my ($TypeId, $LibVersion) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012449 return () if(not $TypeId);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012450 return () if(not $TypeInfo{$LibVersion}{$TypeId});
12451 return %{$TypeInfo{$LibVersion}{$TypeId}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012452}
12453
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012454sub isPrivateData($)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012455{ # non-public global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012456 my $Symbol = $_[0];
12457 return ($Symbol=~/\A(_ZGV|_ZTI|_ZTS|_ZTT|_ZTV|_ZTC|_ZThn|_ZTv0_n)/);
12458}
12459
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012460sub isInLineInst($$$) {
12461 return (isTemplateInstance(@_) and not isTemplateSpec(@_));
12462}
12463
12464sub isTemplateInstance($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012465{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012466 my ($Symbol, $SInfo, $LibVersion) = @_;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012467 if($CheckObjectsOnly)
12468 {
12469 if($Symbol!~/\A(_Z|\?)/) {
12470 return 0;
12471 }
12472 if(my $Signature = $tr_name{$Symbol})
12473 {
12474 if(index($Signature,">")==-1) {
12475 return 0;
12476 }
12477 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
12478 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012479 if(index($ShortName,"<")!=-1
12480 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012481 return 1;
12482 }
12483 }
12484 }
12485 }
12486 else
12487 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012488 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012489 {
12490 if(my $ClassName = $TypeInfo{$LibVersion}{$ClassId}{"Name"})
12491 {
12492 if(index($ClassName,"<")!=-1) {
12493 return 1;
12494 }
12495 }
12496 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012497 if(my $ShortName = $SInfo->{"ShortName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012498 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012499 if(index($ShortName,"<")!=-1
12500 and index($ShortName,">")!=-1) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012501 return 1;
12502 }
12503 }
12504 }
12505 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012506}
12507
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012508sub isTemplateSpec($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012509{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012510 my ($Symbol, $SInfo, $LibVersion) = @_;
12511 if(my $ClassId = $SInfo->{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012512 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012513 if($TypeInfo{$LibVersion}{$ClassId}{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012514 { # class specialization
12515 return 1;
12516 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012517 elsif($SInfo->{"Spec"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012518 { # method specialization
12519 return 1;
12520 }
12521 }
12522 return 0;
12523}
12524
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012525sub symbolFilter($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012526{ # some special cases when the symbol cannot be imported
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012527 my ($Symbol, $LibVersion, $Type, $Level) = @_;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040012528 if(isPrivateData($Symbol))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012529 { # non-public global data
12530 return 0;
12531 }
12532 if($CheckObjectsOnly) {
12533 return 0 if($Symbol=~/\A(_init|_fini)\Z/);
12534 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012535 if($CheckHeadersOnly and not checkDump($LibVersion, "2.7"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012536 { # support for old ABI dumps in --headers-only mode
12537 foreach my $Pos (keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
12538 {
12539 if(my $Pid = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$Pos}{"type"})
12540 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012541 my $PType = $TypeInfo{$LibVersion}{$Pid}{"Type"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012542 if(not $PType or $PType eq "Unknown") {
12543 return 0;
12544 }
12545 }
12546 }
12547 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012548 if($Type=~/Affected/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012549 {
12550 my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012551 if($SkipSymbols{$LibVersion}{$Symbol})
12552 { # user defined symbols to ignore
12553 return 0;
12554 }
12555 my $NameSpace = $CompleteSignature{$LibVersion}{$Symbol}{"NameSpace"};
12556 if(not $NameSpace and $ClassId)
12557 { # class methods have no "NameSpace" attribute
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012558 $NameSpace = $TypeInfo{$LibVersion}{$ClassId}{"NameSpace"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012559 }
12560 if($NameSpace)
12561 { # user defined namespaces to ignore
12562 if($SkipNameSpaces{$LibVersion}{$NameSpace}) {
12563 return 0;
12564 }
12565 foreach my $NS (keys(%{$SkipNameSpaces{$LibVersion}}))
12566 { # nested namespaces
12567 if($NameSpace=~/\A\Q$NS\E(\:\:|\Z)/) {
12568 return 0;
12569 }
12570 }
12571 }
12572 if(my $Header = $CompleteSignature{$LibVersion}{$Symbol}{"Header"})
12573 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012574 if(my $Skip = skipHeader($Header, $LibVersion))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012575 { # --skip-headers or <skip_headers> (not <skip_including>)
12576 if($Skip==1) {
12577 return 0;
12578 }
12579 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012580 }
12581 if($SymbolsListPath and not $SymbolsList{$Symbol})
12582 { # user defined symbols
12583 return 0;
12584 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040012585 if($SkipSymbolsListPath and $SkipSymbolsList{$Symbol})
12586 { # user defined symbols
12587 return 0;
12588 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012589 if($AppPath and not $SymbolsList_App{$Symbol})
12590 { # user defined symbols (in application)
12591 return 0;
12592 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012593 if(not selectSymbol($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $Level, $LibVersion))
12594 { # non-target symbols
12595 return 0;
12596 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012597 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012598 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012599 if($CheckObjectsOnly)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012600 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012601 if(isTemplateInstance($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion)) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012602 return 0;
12603 }
12604 }
12605 else
12606 {
12607 if($CompleteSignature{$LibVersion}{$Symbol}{"InLine"}
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040012608 or isInLineInst($Symbol, $CompleteSignature{$LibVersion}{$Symbol}, $LibVersion))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012609 {
12610 if($ClassId and $CompleteSignature{$LibVersion}{$Symbol}{"Virt"})
12611 { # inline virtual methods
12612 if($Type=~/InlineVirt/) {
12613 return 1;
12614 }
12615 my $Allocable = (not isCopyingClass($ClassId, $LibVersion));
12616 if(not $Allocable)
12617 { # check bases
12618 foreach my $DCId (get_sub_classes($ClassId, $LibVersion, 1))
12619 {
12620 if(not isCopyingClass($DCId, $LibVersion))
12621 { # exists a derived class without default c-tor
12622 $Allocable=1;
12623 last;
12624 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012625 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012626 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012627 if(not $Allocable) {
12628 return 0;
12629 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012630 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012631 else
12632 { # inline non-virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012633 return 0;
12634 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012635 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012636 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012637 }
12638 }
12639 return 1;
12640}
12641
12642sub mergeImpl()
12643{
12644 my $DiffCmd = get_CmdPath("diff");
12645 if(not $DiffCmd) {
12646 exitStatus("Not_Found", "can't find \"diff\"");
12647 }
12648 foreach my $Interface (sort keys(%{$Symbol_Library{1}}))
12649 { # implementation changes
12650 next if($CompleteSignature{1}{$Interface}{"Private"});
12651 next if(not $CompleteSignature{1}{$Interface}{"Header"} and not $CheckObjectsOnly);
12652 next if(not $Symbol_Library{2}{$Interface} and not $Symbol_Library{2}{$SymVer{2}{$Interface}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012653 if(not symbolFilter($Interface, 1, "Affected", "Binary")) {
12654 next;
12655 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012656 my $Impl1 = canonifyImpl($Interface_Impl{1}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012657 next if(not $Impl1);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012658 my $Impl2 = canonifyImpl($Interface_Impl{2}{$Interface});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012659 next if(not $Impl2);
12660 if($Impl1 ne $Impl2)
12661 {
12662 writeFile("$TMP_DIR/impl1", $Impl1);
12663 writeFile("$TMP_DIR/impl2", $Impl2);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012664 my $Diff = `$DiffCmd -rNau \"$TMP_DIR/impl1\" \"$TMP_DIR/impl2\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012665 $Diff=~s/(---|\+\+\+).+\n//g;
12666 $Diff=~s/[ ]{3,}/ /g;
12667 $Diff=~s/\n\@\@/\n \n\@\@/g;
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012668 unlink("$TMP_DIR/impl1");
12669 unlink("$TMP_DIR/impl2");
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040012670 %{$CompatProblems_Impl{$Interface}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012671 "Diff" => get_CodeView($Diff) );
12672 }
12673 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012674
12675 # clean memory
12676 %Interface_Impl = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012677}
12678
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012679sub canonifyImpl($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012680{
12681 my $FuncBody= $_[0];
12682 return "" if(not $FuncBody);
12683 $FuncBody=~s/0x[a-f\d]+/0x?/g;# addr
12684 $FuncBody=~s/((\A|\n)[a-z]+[\t ]+)[a-f\d]+([^x]|\Z)/$1?$3/g;# call, jump
12685 $FuncBody=~s/# [a-f\d]+ /# ? /g;# call, jump
12686 $FuncBody=~s/%([a-z]+[a-f\d]*)/\%reg/g;# registers
12687 while($FuncBody=~s/\nnop[ \t]*(\n|\Z)/$1/g){};# empty op
12688 $FuncBody=~s/<.+?\.cpp.+?>/<name.cpp>/g;
12689 $FuncBody=~s/(\A|\n)[a-f\d]+ </$1? </g;# 5e74 <_ZN...
12690 $FuncBody=~s/\.L\d+/.L/g;
12691 $FuncBody=~s/#(-?)\d+/#$1?/g;# r3, [r3, #120]
12692 $FuncBody=~s/[\n]{2,}/\n/g;
12693 return $FuncBody;
12694}
12695
12696sub get_CodeView($)
12697{
12698 my $Code = $_[0];
12699 my $View = "";
12700 foreach my $Line (split(/\n/, $Code))
12701 {
12702 if($Line=~s/\A(\+|-)/$1 /g)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012703 { # bold line
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012704 $View .= "<tr><td><b>".htmlSpecChars($Line)."</b></td></tr>\n";
12705 }
12706 else {
12707 $View .= "<tr><td>".htmlSpecChars($Line)."</td></tr>\n";
12708 }
12709 }
12710 return "<table class='code_view'>$View</table>\n";
12711}
12712
12713sub getImplementations($$)
12714{
12715 my ($LibVersion, $Path) = @_;
12716 return if(not $LibVersion or not -e $Path);
12717 if($OSgroup eq "macos")
12718 {
12719 my $OtoolCmd = get_CmdPath("otool");
12720 if(not $OtoolCmd) {
12721 exitStatus("Not_Found", "can't find \"otool\"");
12722 }
12723 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012724 foreach my $Line (split(/\n/, `$OtoolCmd -tv \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012725 {
12726 if($Line=~/\A\s*_(\w+)\s*:/i) {
12727 $CurInterface = $1;
12728 }
12729 elsif($Line=~/\A\s*[\da-z]+\s+(.+?)\Z/i) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012730 $Interface_Impl{$LibVersion}{$CurInterface} .= $1."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012731 }
12732 }
12733 }
12734 else
12735 {
12736 my $ObjdumpCmd = get_CmdPath("objdump");
12737 if(not $ObjdumpCmd) {
12738 exitStatus("Not_Found", "can't find \"objdump\"");
12739 }
12740 my $CurInterface = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040012741 foreach my $Line (split(/\n/, `$ObjdumpCmd -d \"$Path\" 2>\"$TMP_DIR/null\"`))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012742 {
12743 if($Line=~/\A[\da-z]+\s+<(\w+)>/i) {
12744 $CurInterface = $1;
12745 }
12746 else
12747 { # x86: 51fa:(\t)89 e5 (\t)mov %esp,%ebp
12748 # arm: 5020:(\t)e24cb004(\t)sub(\t)fp, ip, #4(\t); 0x4
12749 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 +040012750 $Interface_Impl{$LibVersion}{$CurInterface} .= $2."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012751 }
12752 }
12753 }
12754 }
12755}
12756
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012757sub detectAdded($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012758{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012759 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012760 foreach my $Symbol (keys(%{$Symbol_Library{2}}))
12761 {
12762 if(link_symbol($Symbol, 1, "+Deps"))
12763 { # linker can find a new symbol
12764 # in the old-version library
12765 # So, it's not a new symbol
12766 next;
12767 }
12768 if(my $VSym = $SymVer{2}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012769 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012770 next;
12771 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012772 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012773 }
12774}
12775
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012776sub detectRemoved($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012777{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012778 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012779 foreach my $Symbol (keys(%{$Symbol_Library{1}}))
12780 {
12781 if($CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012782 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012783 }
12784 if(link_symbol($Symbol, 2, "+Deps"))
12785 { # linker can find an old symbol
12786 # in the new-version library
12787 next;
12788 }
12789 if(my $VSym = $SymVer{1}{$Symbol}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012790 and index($Symbol,"\@")==-1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012791 next;
12792 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012793 $RemovedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012794 }
12795}
12796
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012797sub mergeLibs($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012798{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012799 my $Level = $_[0];
12800 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012801 { # checking added symbols
12802 next if($CompleteSignature{2}{$Symbol}{"Private"});
12803 next if(not $CompleteSignature{2}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012804 next if(not symbolFilter($Symbol, 2, "Affected + InlineVirt", $Level));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012805 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012806 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012807 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012808 { # checking removed symbols
12809 next if($CompleteSignature{1}{$Symbol}{"Private"});
12810 next if(not $CompleteSignature{1}{$Symbol}{"Header"} and not $CheckObjectsOnly);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012811 if(index($Symbol, "_ZTV")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012812 { # skip v-tables for templates, that should not be imported by applications
12813 next if($tr_name{$Symbol}=~/</);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012814 if(my $CName = $VTableClass{$Symbol})
12815 {
12816 if(not keys(%{$ClassMethods{$Level}{1}{$CName}}))
12817 { # vtables for "private" classes
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012818 # use case: vtable for QDragManager (Qt 4.5.3 to 4.6.0) became HIDDEN symbol
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040012819 next;
12820 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012821 }
12822 }
12823 else {
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040012824 next if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012825 }
12826 if($CompleteSignature{1}{$Symbol}{"PureVirt"})
12827 { # symbols for pure virtual methods cannot be called by clients
12828 next;
12829 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012830 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012831 }
12832}
12833
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012834sub checkDump($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012835{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012836 my ($LibVersion, $V) = @_;
12837 if(defined $Cache{"checkDump"}{$LibVersion}{$V}) {
12838 return $Cache{"checkDump"}{$LibVersion}{$V};
12839 }
12840 return ($Cache{"checkDump"}{$LibVersion}{$V} = (not $UsedDump{$LibVersion}{"V"} or cmpVersions($UsedDump{$LibVersion}{"V"}, $V)>=0));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012841}
12842
12843sub detectAdded_H($)
12844{
12845 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012846 foreach my $Symbol (sort keys(%{$CompleteSignature{2}}))
12847 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012848 if($Level eq "Source")
12849 { # remove symbol version
12850 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12851 $Symbol=$SN;
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012852
12853 if($CompleteSignature{2}{$Symbol}{"Artificial"})
12854 { # skip artificial constructors
12855 next;
12856 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012857 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012858 if(not $CompleteSignature{2}{$Symbol}{"Header"}
12859 or not $CompleteSignature{2}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012860 next;
12861 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012862 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012863 next;
12864 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012865 if(not defined $CompleteSignature{1}{$Symbol}
12866 or not $CompleteSignature{1}{$Symbol}{"MnglName"})
12867 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012868 if($UsedDump{2}{"SrcBin"})
12869 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012870 if($UsedDump{1}{"BinOnly"} or not checkDump(1, "2.11"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012871 { # support for old and different (!) ABI dumps
12872 if(not $CompleteSignature{2}{$Symbol}{"Virt"}
12873 and not $CompleteSignature{2}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012874 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012875 if($CheckHeadersOnly)
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012876 {
12877 if(my $Lang = $CompleteSignature{2}{$Symbol}{"Lang"})
12878 {
12879 if($Lang eq "C")
12880 { # support for old ABI dumps: missed extern "C" functions
12881 next;
12882 }
12883 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012884 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012885 else
12886 {
12887 if(not link_symbol($Symbol, 2, "-Deps"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040012888 { # skip added inline symbols and const global data
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012889 next;
12890 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012891 }
12892 }
12893 }
12894 }
12895 $AddedInt{$Level}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012896 }
12897 }
12898}
12899
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012900sub detectRemoved_H($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012901{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012902 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012903 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
12904 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012905 if($Level eq "Source")
12906 { # remove symbol version
12907 my ($SN, $SS, $SV) = separate_symbol($Symbol);
12908 $Symbol=$SN;
12909 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012910 if(not $CompleteSignature{1}{$Symbol}{"Header"}
12911 or not $CompleteSignature{1}{$Symbol}{"MnglName"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012912 next;
12913 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012914 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012915 next;
12916 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012917 if(not defined $CompleteSignature{2}{$Symbol}
12918 or not $CompleteSignature{2}{$Symbol}{"MnglName"})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012919 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012920 if($UsedDump{1}{"SrcBin"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012921 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040012922 if($UsedDump{2}{"BinOnly"} or not checkDump(2, "2.11"))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012923 { # support for old and different (!) ABI dumps
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012924 if(not $CompleteSignature{1}{$Symbol}{"Virt"}
12925 and not $CompleteSignature{1}{$Symbol}{"PureVirt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012926 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012927 if($CheckHeadersOnly)
12928 { # skip all removed symbols
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012929 if(my $Lang = $CompleteSignature{1}{$Symbol}{"Lang"})
12930 {
12931 if($Lang eq "C")
12932 { # support for old ABI dumps: missed extern "C" functions
12933 next;
12934 }
12935 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012936 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040012937 else
12938 {
12939 if(not link_symbol($Symbol, 1, "-Deps"))
12940 { # skip removed inline symbols
12941 next;
12942 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012943 }
12944 }
12945 }
12946 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040012947 if(not checkDump(1, "2.15"))
12948 {
12949 if($Symbol=~/_IT_E\Z/)
12950 { # _ZN28QExplicitlySharedDataPointerI22QSslCertificatePrivateEC1IT_EERKS_IT_E
12951 next;
12952 }
12953 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012954 if(not $CompleteSignature{1}{$Symbol}{"Class"})
12955 {
12956 if(my $Short = $CompleteSignature{1}{$Symbol}{"ShortName"})
12957 {
12958 if(defined $Constants{2}{$Short})
12959 {
12960 my $Val = $Constants{2}{$Short}{"Value"};
12961 if(defined $Func_ShortName{2}{$Val})
12962 { # old name defined to new
12963 next;
12964 }
12965 }
12966 }
12967
12968 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012969 $RemovedInt{$Level}{$Symbol} = 1;
12970 if($Level eq "Source")
12971 { # search for a source-compatible equivalent
12972 setAlternative($Symbol, $Level);
12973 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012974 }
12975 }
12976}
12977
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012978sub mergeHeaders($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012979{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012980 my $Level = $_[0];
12981 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040012982 { # checking added symbols
12983 next if($CompleteSignature{2}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040012984 next if($CompleteSignature{2}{$Symbol}{"Private"});
12985 next if(not symbolFilter($Symbol, 2, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040012986 if($Level eq "Binary")
12987 {
12988 if($CompleteSignature{2}{$Symbol}{"InLine"})
12989 {
12990 if(not $CompleteSignature{2}{$Symbol}{"Virt"})
12991 { # skip inline non-virtual functions
12992 next;
12993 }
12994 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040012995 }
12996 else
12997 { # Source
12998 if($SourceAlternative_B{$Symbol}) {
12999 next;
13000 }
13001 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013002 %{$CompatProblems{$Level}{$Symbol}{"Added_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013003 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013004 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013005 { # checking removed symbols
13006 next if($CompleteSignature{1}{$Symbol}{"PureVirt"});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013007 next if($CompleteSignature{1}{$Symbol}{"Private"});
13008 next if(not symbolFilter($Symbol, 1, "Affected", $Level));
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013009 if($Level eq "Binary")
13010 {
13011 if($CompleteSignature{1}{$Symbol}{"InLine"})
13012 {
13013 if(not $CompleteSignature{1}{$Symbol}{"Virt"})
13014 { # skip inline non-virtual functions
13015 next;
13016 }
13017 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013018 }
13019 else
13020 { # Source
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013021 if(my $Alt = $SourceAlternative{$Symbol})
13022 {
13023 if(defined $CompleteSignature{1}{$Alt}
13024 and $CompleteSignature{1}{$Symbol}{"Const"})
13025 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013026 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013027 %{$CompatProblems{$Level}{$Symbol}{"Removed_Const_Overload"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013028 "Type_Name"=>$TypeInfo{1}{$Cid}{"Name"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013029 "Target"=>get_Signature($Alt, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013030 }
13031 else
13032 { # do NOT show removed symbol
13033 next;
13034 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013035 }
13036 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013037 %{$CompatProblems{$Level}{$Symbol}{"Removed_Symbol"}{""}}=();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013038 }
13039}
13040
13041sub addParamNames($)
13042{
13043 my $LibraryVersion = $_[0];
13044 return if(not keys(%AddIntParams));
13045 my $SecondVersion = $LibraryVersion==1?2:1;
13046 foreach my $Interface (sort keys(%{$CompleteSignature{$LibraryVersion}}))
13047 {
13048 next if(not keys(%{$AddIntParams{$Interface}}));
13049 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibraryVersion}{$Interface}{"Param"}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013050 { # add absent parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013051 my $ParamName = $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"};
13052 if($ParamName=~/\Ap\d+\Z/ and my $NewParamName = $AddIntParams{$Interface}{$ParamPos})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013053 { # names from the external file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013054 if(defined $CompleteSignature{$SecondVersion}{$Interface}
13055 and defined $CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos})
13056 {
13057 if($CompleteSignature{$SecondVersion}{$Interface}{"Param"}{$ParamPos}{"name"}=~/\Ap\d+\Z/) {
13058 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13059 }
13060 }
13061 else {
13062 $CompleteSignature{$LibraryVersion}{$Interface}{"Param"}{$ParamPos}{"name"} = $NewParamName;
13063 }
13064 }
13065 }
13066 }
13067}
13068
13069sub detectChangedTypedefs()
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013070{ # detect changed typedefs to show
13071 # correct function signatures
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013072 foreach my $Typedef (keys(%{$Typedef_BaseName{1}}))
13073 {
13074 next if(not $Typedef);
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013075 my $BName1 = $Typedef_BaseName{1}{$Typedef};
13076 if(not $BName1 or isAnon($BName1)) {
13077 next;
13078 }
13079 my $BName2 = $Typedef_BaseName{2}{$Typedef};
13080 if(not $BName2 or isAnon($BName2)) {
13081 next;
13082 }
13083 if($BName1 ne $BName2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013084 $ChangedTypedef{$Typedef} = 1;
13085 }
13086 }
13087}
13088
13089sub get_symbol_suffix($$)
13090{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013091 my ($Symbol, $Full) = @_;
13092 my ($SN, $SO, $SV) = separate_symbol($Symbol);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040013093 $Symbol=$SN; # remove version
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013094 my $Signature = $tr_name{$Symbol};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013095 my $Suffix = substr($Signature, find_center($Signature, "("));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013096 if(not $Full) {
13097 $Suffix=~s/(\))\s*(const volatile|volatile const|const|volatile)\Z/$1/g;
13098 }
13099 return $Suffix;
13100}
13101
13102sub get_symbol_prefix($$)
13103{
13104 my ($Symbol, $LibVersion) = @_;
13105 my $ShortName = $CompleteSignature{$LibVersion}{$Symbol}{"ShortName"};
13106 if(my $ClassId = $CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13107 { # methods
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013108 $ShortName = $TypeInfo{$LibVersion}{$ClassId}{"Name"}."::".$ShortName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013109 }
13110 return $ShortName;
13111}
13112
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013113sub setAlternative($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013114{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013115 my $Symbol = $_[0];
13116 my $PSymbol = $Symbol;
13117 if(not defined $CompleteSignature{2}{$PSymbol}
13118 or (not $CompleteSignature{2}{$PSymbol}{"MnglName"}
13119 and not $CompleteSignature{2}{$PSymbol}{"ShortName"}))
13120 { # search for a pair
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013121 if(my $ShortName = $CompleteSignature{1}{$PSymbol}{"ShortName"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013122 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013123 if($CompleteSignature{1}{$PSymbol}{"Data"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013124 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013125 if($PSymbol=~s/L(\d+$ShortName(E)\Z)/$1/
13126 or $PSymbol=~s/(\d+$ShortName(E)\Z)/L$1/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013127 {
13128 if(defined $CompleteSignature{2}{$PSymbol}
13129 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13130 {
13131 $SourceAlternative{$Symbol} = $PSymbol;
13132 $SourceAlternative_B{$PSymbol} = $Symbol;
13133 if(not defined $CompleteSignature{1}{$PSymbol}
13134 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13135 $SourceReplacement{$Symbol} = $PSymbol;
13136 }
13137 }
13138 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013139 }
13140 else
13141 {
13142 foreach my $Sp ("KV", "VK", "K", "V")
13143 {
13144 if($PSymbol=~s/\A_ZN$Sp/_ZN/
13145 or $PSymbol=~s/\A_ZN/_ZN$Sp/)
13146 {
13147 if(defined $CompleteSignature{2}{$PSymbol}
13148 and $CompleteSignature{2}{$PSymbol}{"MnglName"})
13149 {
13150 $SourceAlternative{$Symbol} = $PSymbol;
13151 $SourceAlternative_B{$PSymbol} = $Symbol;
13152 if(not defined $CompleteSignature{1}{$PSymbol}
13153 or not $CompleteSignature{1}{$PSymbol}{"MnglName"}) {
13154 $SourceReplacement{$Symbol} = $PSymbol;
13155 }
13156 }
13157 }
13158 $PSymbol = $Symbol;
13159 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013160 }
13161 }
13162 }
13163 return "";
13164}
13165
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013166sub getSymKind($$)
13167{
13168 my ($Symbol, $LibVersion) = @_;
13169 if($CompleteSignature{$LibVersion}{$Symbol}{"Data"})
13170 {
13171 return "Global_Data";
13172 }
13173 elsif($CompleteSignature{$LibVersion}{$Symbol}{"Class"})
13174 {
13175 return "Method";
13176 }
13177 return "Function";
13178}
13179
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040013180sub mergeSymbols($)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013181{
13182 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013183 my %SubProblems = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013184
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013185 mergeBases($Level);
13186
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013187 my %AddedOverloads = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013188 foreach my $Symbol (sort keys(%{$AddedInt{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013189 { # check all added exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013190 if(not $CompleteSignature{2}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013191 next;
13192 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013193 if(defined $CompleteSignature{1}{$Symbol}
13194 and $CompleteSignature{1}{$Symbol}{"Header"})
13195 { # double-check added symbol
13196 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013197 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013198 if(not symbolFilter($Symbol, 2, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013199 next;
13200 }
13201 if($Symbol=~/\A(_Z|\?)/)
13202 { # C++
13203 $AddedOverloads{get_symbol_prefix($Symbol, 2)}{get_symbol_suffix($Symbol, 1)} = $Symbol;
13204 }
13205 if(my $OverriddenMethod = $CompleteSignature{2}{$Symbol}{"Override"})
13206 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013207 my $Cid = $CompleteSignature{2}{$Symbol}{"Class"};
13208 my $AffectedClass_Name = $TypeInfo{2}{$Cid}{"Name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013209 if(defined $CompleteSignature{1}{$OverriddenMethod} and $CompleteSignature{1}{$OverriddenMethod}{"Virt"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013210 and not $CompleteSignature{1}{$OverriddenMethod}{"Private"})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013211 {
13212 if($TName_Tid{1}{$AffectedClass_Name})
13213 { # class should exist in previous version
13214 if(not isCopyingClass($TName_Tid{1}{$AffectedClass_Name}, 1))
13215 { # old v-table is NOT copied by old applications
13216 %{$CompatProblems{$Level}{$OverriddenMethod}{"Overridden_Virtual_Method"}{$tr_name{$Symbol}}}=(
13217 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013218 "Target"=>get_Signature($Symbol, 2),
13219 "Old_Value"=>get_Signature($OverriddenMethod, 2),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013220 "New_Value"=>get_Signature($Symbol, 2));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013221 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013222 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013223 }
13224 }
13225 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013226 foreach my $Symbol (sort keys(%{$RemovedInt{$Level}}))
13227 { # check all removed exported symbols
13228 if(not $CompleteSignature{1}{$Symbol}{"Header"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013229 next;
13230 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013231 if(defined $CompleteSignature{2}{$Symbol}
13232 and $CompleteSignature{2}{$Symbol}{"Header"})
13233 { # double-check removed symbol
13234 next;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013235 }
13236 if($CompleteSignature{1}{$Symbol}{"Private"})
13237 { # skip private methods
13238 next;
13239 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013240 if(not symbolFilter($Symbol, 1, "Affected", $Level)) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013241 next;
13242 }
13243 $CheckedSymbols{$Level}{$Symbol} = 1;
13244 if(my $OverriddenMethod = $CompleteSignature{1}{$Symbol}{"Override"})
13245 { # register virtual overridings
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013246 my $Cid = $CompleteSignature{1}{$Symbol}{"Class"};
13247 my $AffectedClass_Name = $TypeInfo{1}{$Cid}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013248 if(defined $CompleteSignature{2}{$OverriddenMethod}
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013249 and $CompleteSignature{2}{$OverriddenMethod}{"Virt"})
13250 {
13251 if($TName_Tid{2}{$AffectedClass_Name})
13252 { # class should exist in newer version
13253 if(not isCopyingClass($CompleteSignature{1}{$Symbol}{"Class"}, 1))
13254 { # old v-table is NOT copied by old applications
13255 %{$CompatProblems{$Level}{$Symbol}{"Overridden_Virtual_Method_B"}{$tr_name{$OverriddenMethod}}}=(
13256 "Type_Name"=>$AffectedClass_Name,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013257 "Target"=>get_Signature($OverriddenMethod, 1),
13258 "Old_Value"=>get_Signature($Symbol, 1),
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013259 "New_Value"=>get_Signature($OverriddenMethod, 1));
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013260 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013261 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013262 }
13263 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013264 if($Level eq "Binary"
13265 and $OSgroup eq "windows")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013266 { # register the reason of symbol name change
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013267 if(my $NewSym = $mangled_name{2}{$tr_name{$Symbol}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013268 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013269 if($AddedInt{$Level}{$NewSym})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013270 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013271 if($CompleteSignature{1}{$Symbol}{"Static"} ne $CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013272 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013273 if($CompleteSignature{2}{$NewSym}{"Static"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013274 {
13275 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Static"}{$tr_name{$Symbol}}}=(
13276 "Target"=>$tr_name{$Symbol},
13277 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013278 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013279 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013280 else
13281 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013282 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Static"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013283 "Target"=>$tr_name{$Symbol},
13284 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013285 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013286 }
13287 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013288 if($CompleteSignature{1}{$Symbol}{"Virt"} ne $CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013289 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013290 if($CompleteSignature{2}{$NewSym}{"Virt"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013291 {
13292 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Virtual"}{$tr_name{$Symbol}}}=(
13293 "Target"=>$tr_name{$Symbol},
13294 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013295 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013296 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013297 else
13298 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013299 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Became_Non_Virtual"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013300 "Target"=>$tr_name{$Symbol},
13301 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013302 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013303 }
13304 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013305 my $RTId1 = $CompleteSignature{1}{$Symbol}{"Return"};
13306 my $RTId2 = $CompleteSignature{2}{$NewSym}{"Return"};
13307 my $RTName1 = $TypeInfo{1}{$RTId1}{"Name"};
13308 my $RTName2 = $TypeInfo{2}{$RTId2}{"Name"};
13309 if($RTName1 ne $RTName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013310 {
13311 my $ProblemType = "Symbol_Changed_Return";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013312 if($CompleteSignature{1}{$Symbol}{"Data"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013313 $ProblemType = "Global_Data_Symbol_Changed_Type";
13314 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013315 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{$tr_name{$Symbol}}}=(
13316 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013317 "Old_Type"=>$RTName1,
13318 "New_Type"=>$RTName2,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013319 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013320 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013321 }
13322 }
13323 }
13324 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013325 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013326 { # C++
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013327 my $Prefix = get_symbol_prefix($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013328 if(my @Overloads = sort keys(%{$AddedOverloads{$Prefix}})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013329 and not $AddedOverloads{$Prefix}{get_symbol_suffix($Symbol, 1)})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013330 { # changed signature: params, "const"-qualifier
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013331 my $NewSym = $AddedOverloads{$Prefix}{$Overloads[0]};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013332 if($CompleteSignature{1}{$Symbol}{"Constructor"})
13333 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013334 if($Symbol=~/(C1E|C2E)/)
13335 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013336 my $CtorType = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013337 $NewSym=~s/(C1E|C2E)/$CtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013338 }
13339 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013340 elsif($CompleteSignature{1}{$Symbol}{"Destructor"})
13341 {
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040013342 if($Symbol=~/(D0E|D1E|D2E)/)
13343 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013344 my $DtorType = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013345 $NewSym=~s/(D0E|D1E|D2E)/$DtorType/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013346 }
13347 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013348 my $NS1 = $CompleteSignature{1}{$Symbol}{"NameSpace"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013349 my $NS2 = $CompleteSignature{2}{$NewSym}{"NameSpace"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013350 if((not $NS1 and not $NS2) or ($NS1 and $NS2 and $NS1 eq $NS2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013351 { # from the same class and namespace
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013352 if($CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013353 and not $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013354 { # "const" to non-"const"
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013355 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013356 "Type_Name"=>$TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013357 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013358 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013359 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013360 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013361 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013362 elsif(not $CompleteSignature{1}{$Symbol}{"Const"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013363 and $CompleteSignature{2}{$NewSym}{"Const"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013364 { # non-"const" to "const"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013365 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Const"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013366 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013367 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013368 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013369 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013370 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013371 if($CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013372 and not $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013373 { # "volatile" to non-"volatile"
13374
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013375 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013376 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013377 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013378 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013379 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013380 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013381 elsif(not $CompleteSignature{1}{$Symbol}{"Volatile"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013382 and $CompleteSignature{2}{$NewSym}{"Volatile"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013383 { # non-"volatile" to "volatile"
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013384 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Volatile"}{$tr_name{$Symbol}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013385 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013386 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013387 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013388 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013389 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013390 if(get_symbol_suffix($Symbol, 0) ne get_symbol_suffix($NewSym, 0))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013391 { # params list
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013392 %{$CompatProblems{$Level}{$Symbol}{"Symbol_Changed_Parameters"}{$tr_name{$Symbol}}}=(
13393 "Target"=>$tr_name{$Symbol},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013394 "New_Signature"=>get_Signature($NewSym, 2),
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013395 "Old_Value"=>$Symbol,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013396 "New_Value"=>$NewSym );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013397 }
13398 }
13399 }
13400 }
13401 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013402 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
13403 { # checking symbols
13404 my ($SN, $SS, $SV) = separate_symbol($Symbol);
13405 if($Level eq "Source")
13406 { # remove symbol version
13407 $Symbol=$SN;
13408 }
13409 else
13410 { # Binary
13411 if(not $SV)
13412 { # symbol without version
13413 if(my $VSym = $SymVer{1}{$Symbol})
13414 { # the symbol is linked with versioned symbol
13415 if($CompleteSignature{2}{$VSym}{"MnglName"})
13416 { # show report for symbol@ver only
13417 next;
13418 }
13419 elsif(not link_symbol($VSym, 2, "-Deps"))
13420 { # changed version: sym@v1 to sym@v2
13421 # do NOT show report for symbol
13422 next;
13423 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013424 }
13425 }
13426 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013427 my $PSymbol = $Symbol;
13428 if($Level eq "Source"
13429 and my $S = $SourceReplacement{$Symbol})
13430 { # take a source-compatible replacement function
13431 $PSymbol = $S;
13432 }
13433 if($CompleteSignature{1}{$Symbol}{"Private"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013434 { # private symbols
13435 next;
13436 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013437 if(not defined $CompleteSignature{1}{$Symbol}
13438 or not defined $CompleteSignature{2}{$PSymbol})
13439 { # no info
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013440 next;
13441 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013442 if(not $CompleteSignature{1}{$Symbol}{"MnglName"}
13443 or not $CompleteSignature{2}{$PSymbol}{"MnglName"})
13444 { # no mangled name
13445 next;
13446 }
13447 if(not $CompleteSignature{1}{$Symbol}{"Header"}
13448 or not $CompleteSignature{2}{$PSymbol}{"Header"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013449 { # without a header
13450 next;
13451 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013452
13453 if(not $CompleteSignature{1}{$Symbol}{"PureVirt"}
13454 and $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13455 { # became pure
13456 next;
13457 }
13458 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13459 and not $CompleteSignature{2}{$PSymbol}{"PureVirt"})
13460 { # became non-pure
13461 next;
13462 }
13463
13464 if(not symbolFilter($Symbol, 1, "Affected + InlineVirt", $Level))
13465 { # exported, target, inline virtual and pure virtual
13466 next;
13467 }
13468 if(not symbolFilter($PSymbol, 2, "Affected + InlineVirt", $Level))
13469 { # exported, target, inline virtual and pure virtual
13470 next;
13471 }
13472
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013473 if(checkDump(1, "2.13") and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013474 {
13475 if($CompleteSignature{1}{$Symbol}{"Data"}
13476 and $CompleteSignature{2}{$PSymbol}{"Data"})
13477 {
13478 my $Value1 = $CompleteSignature{1}{$Symbol}{"Value"};
13479 my $Value2 = $CompleteSignature{2}{$PSymbol}{"Value"};
13480 if(defined $Value1)
13481 {
13482 $Value1 = showVal($Value1, $CompleteSignature{1}{$Symbol}{"Return"}, 1);
13483 if(defined $Value2)
13484 {
13485 $Value2 = showVal($Value2, $CompleteSignature{2}{$PSymbol}{"Return"}, 2);
13486 if($Value1 ne $Value2)
13487 {
13488 %{$CompatProblems{$Level}{$Symbol}{"Global_Data_Value_Changed"}{""}}=(
13489 "Old_Value"=>$Value1,
13490 "New_Value"=>$Value2,
13491 "Target"=>get_Signature($Symbol, 1) );
13492 }
13493 }
13494 }
13495 }
13496 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040013497
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013498 if($CompleteSignature{2}{$PSymbol}{"Private"})
13499 {
13500 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Private"}{""}}=(
13501 "Target"=>get_Signature_M($PSymbol, 2) );
13502 }
13503 elsif(not $CompleteSignature{1}{$Symbol}{"Protected"}
13504 and $CompleteSignature{2}{$PSymbol}{"Protected"})
13505 {
13506 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Protected"}{""}}=(
13507 "Target"=>get_Signature_M($PSymbol, 2) );
13508 }
13509 elsif($CompleteSignature{1}{$Symbol}{"Protected"}
13510 and not $CompleteSignature{2}{$PSymbol}{"Protected"})
13511 {
13512 %{$CompatProblems{$Level}{$Symbol}{getSymKind($Symbol, 1)."_Became_Public"}{""}}=(
13513 "Target"=>get_Signature_M($PSymbol, 2) );
13514 }
13515
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013516 # checking virtual table
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013517 mergeVirtualTables($Symbol, $Level);
13518
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013519 if($COMPILE_ERRORS)
13520 { # if some errors occurred at the compiling stage
13521 # then some false positives can be skipped here
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013522 if(not $CompleteSignature{1}{$Symbol}{"Data"} and $CompleteSignature{2}{$PSymbol}{"Data"}
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013523 and not $GlobalDataObject{2}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013524 { # missed information about parameters in newer version
13525 next;
13526 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013527 if($CompleteSignature{1}{$Symbol}{"Data"} and not $GlobalDataObject{1}{$Symbol}
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013528 and not $CompleteSignature{2}{$PSymbol}{"Data"})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013529 { # missed information about parameters in older version
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013530 next;
13531 }
13532 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013533 my ($MnglName, $VersionSpec, $SymbolVersion) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013534 # checking attributes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013535 if($CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013536 and not $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13537 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013538 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Static"}{""}}=(
13539 "Target"=>get_Signature($Symbol, 1)
13540 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013541 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013542 elsif(not $CompleteSignature{2}{$PSymbol}{"Static"}
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013543 and $CompleteSignature{1}{$Symbol}{"Static"} and $Symbol=~/\A(_Z|\?)/)
13544 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013545 %{$CompatProblems{$Level}{$Symbol}{"Method_Became_Non_Static"}{""}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013546 "Target"=>get_Signature($Symbol, 1)
13547 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013548 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013549 if(($CompleteSignature{1}{$Symbol}{"Virt"} and $CompleteSignature{2}{$PSymbol}{"Virt"})
13550 or ($CompleteSignature{1}{$Symbol}{"PureVirt"} and $CompleteSignature{2}{$PSymbol}{"PureVirt"}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013551 { # relative position of virtual and pure virtual methods
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013552 if($Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013553 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013554 if(defined $CompleteSignature{1}{$Symbol}{"RelPos"} and defined $CompleteSignature{2}{$PSymbol}{"RelPos"}
13555 and $CompleteSignature{1}{$Symbol}{"RelPos"}!=$CompleteSignature{2}{$PSymbol}{"RelPos"})
13556 { # top-level virtual methods only
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013557 my $Class_Id = $CompleteSignature{1}{$Symbol}{"Class"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013558 my $Class_Name = $TypeInfo{1}{$Class_Id}{"Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013559 if(defined $VirtualTable{1}{$Class_Name} and defined $VirtualTable{2}{$Class_Name}
13560 and $VirtualTable{1}{$Class_Name}{$Symbol}!=$VirtualTable{2}{$Class_Name}{$Symbol})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013561 { # check the absolute position of virtual method (including added and removed methods)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013562 my %Class_Type = get_Type($Class_Id, 1);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013563 my $ProblemType = "Virtual_Method_Position";
13564 if($CompleteSignature{1}{$Symbol}{"PureVirt"}) {
13565 $ProblemType = "Pure_Virtual_Method_Position";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013566 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013567 if(isUsedClass($Class_Id, 1, $Level))
13568 {
13569 my @Affected = ($Symbol, keys(%{$OverriddenMethods{1}{$Symbol}}));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013570 foreach my $ASymbol (@Affected)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013571 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013572 if(not symbolFilter($ASymbol, 1, "Affected", $Level)) {
13573 next;
13574 }
13575 %{$CompatProblems{$Level}{$ASymbol}{$ProblemType}{$tr_name{$MnglName}}}=(
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013576 "Type_Name"=>$Class_Type{"Name"},
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013577 "Old_Value"=>$CompleteSignature{1}{$Symbol}{"RelPos"},
13578 "New_Value"=>$CompleteSignature{2}{$PSymbol}{"RelPos"},
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040013579 "Target"=>get_Signature($Symbol, 1));
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013580 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040013581 $VTableChanged_M{$Class_Type{"Name"}} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013582 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013583 }
13584 }
13585 }
13586 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013587 if($CompleteSignature{1}{$Symbol}{"PureVirt"}
13588 or $CompleteSignature{2}{$PSymbol}{"PureVirt"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013589 { # do NOT check type changes in pure virtuals
13590 next;
13591 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013592 $CheckedSymbols{$Level}{$Symbol} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013593 if($Symbol=~/\A(_Z|\?)/
13594 or keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})==keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013595 { # C/C++: changes in parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013596 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013597 { # checking parameters
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013598 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013599 }
13600 }
13601 else
13602 { # C: added/removed parameters
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013603 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013604 { # checking added parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013605 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013606 my $PType2_Name = $TypeInfo{2}{$PType2_Id}{"Name"};
13607 last if($PType2_Name eq "...");
13608 my $PName = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
13609 my $PName_Old = (defined $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos})?$CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013610 my $ParamPos_Prev = "-1";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013611 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013612 { # added unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013613 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 1);
13614 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType2_Name, $ParamPos, "backward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013615 if($#Positions1==-1 or $#Positions2>$#Positions1) {
13616 $ParamPos_Prev = "lost";
13617 }
13618 }
13619 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013620 $ParamPos_Prev = find_ParamPair_Pos_byName($PName, $Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013621 }
13622 if($ParamPos_Prev eq "lost")
13623 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013624 if($ParamPos>keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013625 {
13626 my $ProblemType = "Added_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013627 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013628 $ProblemType = "Added_Unnamed_Parameter";
13629 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013630 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013631 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013632 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013633 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013634 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013635 }
13636 else
13637 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013638 my %ParamType_Pure = get_PureType($PType2_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013639 my $PairType_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013640 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013641 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType2_Name eq $TypeInfo{1}{$PairType_Id}{"Name"})
13642 and find_ParamPair_Pos_byName($PName_Old, $Symbol, 2) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013643 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013644 if($PName_Old!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013645 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013646 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013647 "Target"=>$PName_Old,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013648 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013649 "Param_Type"=>$PType2_Name,
13650 "Old_Value"=>$PName_Old,
13651 "New_Value"=>$PName,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013652 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013653 }
13654 }
13655 else
13656 {
13657 my $ProblemType = "Added_Middle_Parameter";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013658 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013659 $ProblemType = "Added_Middle_Unnamed_Parameter";
13660 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013661 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013662 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013663 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013664 "Param_Type"=>$PType2_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013665 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013666 }
13667 }
13668 }
13669 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013670 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013671 { # check relevant parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013672 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013673 my $ParamName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013674 # FIXME: find relevant parameter by name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013675 if(defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013676 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013677 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013678 my $ParamName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013679 if($TypeInfo{1}{$PType1_Id}{"Name"} eq $TypeInfo{2}{$PType2_Id}{"Name"}
13680 or ($ParamName1!~/\Ap\d+\Z/i and $ParamName1 eq $ParamName2)) {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013681 mergeParameters($Symbol, $PSymbol, $ParamPos, $ParamPos, $Level, 0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013682 }
13683 }
13684 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013685 foreach my $ParamPos (sort {int($a) <=> int($b)} keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013686 { # checking removed parameters
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040013687 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013688 my $PType1_Name = $TypeInfo{1}{$PType1_Id}{"Name"};
13689 last if($PType1_Name eq "...");
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013690 my $PName = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos}{"name"};
13691 my $PName_New = (defined $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos})?$CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"name"}:"";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013692 my $ParamPos_New = "-1";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013693 if($PName=~/\Ap\d+\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013694 { # removed unnamed parameter ( pN )
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013695 my @Positions1 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 1);
13696 my @Positions2 = find_ParamPair_Pos_byTypeAndPos($PType1_Name, $ParamPos, "forward", $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013697 if($#Positions2==-1 or $#Positions2<$#Positions1) {
13698 $ParamPos_New = "lost";
13699 }
13700 }
13701 else {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013702 $ParamPos_New = find_ParamPair_Pos_byName($PName, $Symbol, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013703 }
13704 if($ParamPos_New eq "lost")
13705 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013706 if($ParamPos>keys(%{$CompleteSignature{2}{$PSymbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013707 {
13708 my $ProblemType = "Removed_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013709 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013710 $ProblemType = "Removed_Unnamed_Parameter";
13711 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013712 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013713 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013714 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013715 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013716 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013717 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013718 elsif($ParamPos<keys(%{$CompleteSignature{1}{$Symbol}{"Param"}})-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013719 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013720 my %ParamType_Pure = get_PureType($PType1_Id, $TypeInfo{1});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013721 my $PairType_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013722 my %PairType_Pure = get_PureType($PairType_Id, $TypeInfo{2});
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013723 if(($ParamType_Pure{"Name"} eq $PairType_Pure{"Name"} or $PType1_Name eq $TypeInfo{2}{$PairType_Id}{"Name"})
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013724 and find_ParamPair_Pos_byName($PName_New, $Symbol, 1) eq "lost")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013725 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013726 if($PName_New!~/\Ap\d+\Z/ and $PName!~/\Ap\d+\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013727 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013728 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013729 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013730 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013731 "Param_Type"=>$PType1_Name,
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013732 "Old_Value"=>$PName,
13733 "New_Value"=>$PName_New,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013734 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013735 }
13736 }
13737 else
13738 {
13739 my $ProblemType = "Removed_Middle_Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013740 if($PName=~/\Ap\d+\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013741 $ProblemType = "Removed_Middle_Unnamed_Parameter";
13742 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040013743 %{$CompatProblems{$Level}{$Symbol}{$ProblemType}{showPos($ParamPos)." Parameter"}}=(
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040013744 "Target"=>$PName,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013745 "Param_Pos"=>$ParamPos,
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013746 "Param_Type"=>$PType1_Name,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013747 "New_Signature"=>get_Signature($Symbol, 2) );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013748 }
13749 }
13750 }
13751 }
13752 }
13753 # checking return type
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013754 my $ReturnType1_Id = $CompleteSignature{1}{$Symbol}{"Return"};
13755 my $ReturnType2_Id = $CompleteSignature{2}{$PSymbol}{"Return"};
13756 %SubProblems = detectTypeChange($ReturnType1_Id, $ReturnType2_Id, "Return", $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013757
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013758 foreach my $SubProblemType (keys(%SubProblems))
13759 {
13760 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13761 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013762 my %ProblemTypes = ();
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013763
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013764 if($CompleteSignature{1}{$Symbol}{"Data"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013765 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013766 if($SubProblemType eq "Return_Type_And_Size") {
13767 $ProblemTypes{"Global_Data_Type_And_Size"} = 1;
13768 }
13769 elsif($SubProblemType eq "Return_Type_Format") {
13770 $ProblemTypes{"Global_Data_Type_Format"} = 1;
13771 }
13772 else {
13773 $ProblemTypes{"Global_Data_Type"} = 1;
13774 }
13775
13776 # quals
13777 if($SubProblemType eq "Return_Type"
13778 or $SubProblemType eq "Return_Type_And_Size"
13779 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013780 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013781 if(my $RR = removedQual($Old_Value, $New_Value, "const"))
13782 { # const to non-const
13783 if($RR==2) {
13784 $ProblemTypes{"Global_Data_Removed_Const"} = 1;
13785 }
13786 else {
13787 $ProblemTypes{"Global_Data_Became_Non_Const"} = 1;
13788 }
13789 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013790 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013791 elsif(my $RA = addedQual($Old_Value, $New_Value, "const"))
13792 { # non-const to const
13793 if($RA==2) {
13794 $ProblemTypes{"Global_Data_Added_Const"} = 1;
13795 }
13796 else {
13797 $ProblemTypes{"Global_Data_Became_Const"} = 1;
13798 }
13799 $ProblemTypes{"Global_Data_Type"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013800 }
13801 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013802 }
13803 else
13804 {
13805 # quals
13806 if($SubProblemType eq "Return_Type"
13807 or $SubProblemType eq "Return_Type_And_Size"
13808 or $SubProblemType eq "Return_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013809 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013810 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013811 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013812 if(addedQual($Old_Value, $New_Value, "volatile"))
13813 {
13814 $ProblemTypes{"Return_Value_Became_Volatile"} = 1;
13815 if($Level ne "Source"
13816 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13817 $ProblemTypes{"Return_Type"} = 1;
13818 }
13819 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013820 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013821 if(my $RA = addedQual($Old_Value, $New_Value, "const"))
13822 {
13823 if($RA==2) {
13824 $ProblemTypes{"Return_Type_Added_Const"} = 1;
13825 }
13826 else {
13827 $ProblemTypes{"Return_Type_Became_Const"} = 1;
13828 }
13829 if($Level ne "Source"
13830 or not cmpBTypes($Old_Value, $New_Value, 1, 2)) {
13831 $ProblemTypes{"Return_Type"} = 1;
13832 }
13833 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013834 }
13835 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013836 if($Level eq "Binary"
13837 and not $CompleteSignature{1}{$Symbol}{"Data"})
13838 {
13839 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
13840 if($Arch1 eq "unknown" or $Arch2 eq "unknown")
13841 { # if one of the architectures is unknown
13842 # then set other arhitecture to unknown too
13843 ($Arch1, $Arch2) = ("unknown", "unknown");
13844 }
13845 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013846 if($UseConv_Real{1}{"R"} and $UseConv_Real{2}{"R"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013847 {
13848 %Conv1 = callingConvention_R_Real($CompleteSignature{1}{$Symbol});
13849 %Conv2 = callingConvention_R_Real($CompleteSignature{2}{$PSymbol});
13850 }
13851 else
13852 {
13853 %Conv1 = callingConvention_R_Model($CompleteSignature{1}{$Symbol}, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
13854 %Conv2 = callingConvention_R_Model($CompleteSignature{2}{$PSymbol}, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
13855 }
13856
13857 if($SubProblemType eq "Return_Type_Became_Void")
13858 {
13859 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13860 { # parameters stack has been affected
13861 if($Conv1{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013862 $ProblemTypes{"Return_Type_Became_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013863 }
13864 elsif($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013865 $ProblemTypes{"Return_Type_Became_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013866 }
13867 }
13868 }
13869 elsif($SubProblemType eq "Return_Type_From_Void")
13870 {
13871 if(keys(%{$CompleteSignature{1}{$Symbol}{"Param"}}))
13872 { # parameters stack has been affected
13873 if($Conv2{"Method"} eq "stack") {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013874 $ProblemTypes{"Return_Type_From_Void_And_Stack_Layout"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013875 }
13876 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013877 $ProblemTypes{"Return_Type_From_Void_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013878 }
13879 }
13880 }
13881 elsif($SubProblemType eq "Return_Type"
13882 or $SubProblemType eq "Return_Type_And_Size"
13883 or $SubProblemType eq "Return_Type_Format")
13884 {
13885 if($Conv1{"Method"} ne $Conv2{"Method"})
13886 {
13887 if($Conv1{"Method"} eq "stack")
13888 { # returns in a register instead of a hidden first parameter
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013889 $ProblemTypes{"Return_Type_From_Stack_To_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013890 }
13891 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013892 $ProblemTypes{"Return_Type_From_Register_To_Stack"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013893 }
13894 }
13895 else
13896 {
13897 if($Conv1{"Method"} eq "reg")
13898 {
13899 if($Conv1{"Registers"} ne $Conv2{"Registers"})
13900 {
13901 if($Conv1{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013902 $ProblemTypes{"Return_Type_And_Register_Was_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013903 }
13904 elsif($Conv2{"Hidden"}) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013905 $ProblemTypes{"Return_Type_And_Register_Became_Hidden_Parameter"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013906 }
13907 else {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013908 $ProblemTypes{"Return_Type_And_Register"} = 1;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040013909 }
13910 }
13911 }
13912 }
13913 }
13914 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013915
13916 if(not keys(%ProblemTypes))
13917 { # default
13918 $ProblemTypes{$SubProblemType} = 1;
13919 }
13920
13921 foreach my $ProblemType (keys(%ProblemTypes))
13922 { # additional
13923 @{$CompatProblems{$Level}{$Symbol}{$ProblemType}{"retval"}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040013924 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013925 }
13926 if($ReturnType1_Id and $ReturnType2_Id)
13927 {
13928 @RecurTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013929 %SubProblems = mergeTypes($ReturnType1_Id, $ReturnType2_Id, $Level);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040013930
13931 if($CompleteSignature{1}{$Symbol}{"Data"})
13932 {
13933 if($Level eq "Binary")
13934 {
13935 if(get_PLevel($ReturnType1_Id, 1)==0)
13936 {
13937 foreach my $SubProblemType (keys(%SubProblems))
13938 { # add "Global_Data_Size" problem
13939 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
13940 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
13941 if($SubProblemType eq "DataType_Size")
13942 { # add a new problem
13943 %{$SubProblems{"Global_Data_Size"}} = %{$SubProblems{$SubProblemType}};
13944 }
13945 }
13946 }
13947 if(not defined $SubProblems{"Global_Data_Size"})
13948 {
13949 if(defined $GlobalDataObject{1}{$Symbol}
13950 and defined $GlobalDataObject{2}{$Symbol})
13951 {
13952 my $Old_Size = $GlobalDataObject{1}{$Symbol};
13953 my $New_Size = $GlobalDataObject{2}{$Symbol};
13954 if($Old_Size!=$New_Size)
13955 {
13956 %{$SubProblems{"Global_Data_Size"}{"retval"}} = (
13957 "Old_Size"=>$Old_Size*$BYTE_SIZE,
13958 "New_Size"=>$New_Size*$BYTE_SIZE );
13959 }
13960 }
13961 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013962 }
13963 }
13964 foreach my $SubProblemType (keys(%SubProblems))
13965 {
13966 foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}}))
13967 {
13968 my $NewLocation = ($SubLocation)?"retval->".$SubLocation:"retval";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013969 %{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013970 "Return_Type_Name"=>$TypeInfo{1}{$ReturnType1_Id}{"Name"} );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013971 @{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013972 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013973 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$ReturnType1_Id}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013974 }
13975 }
13976 }
13977 }
13978
13979 # checking object type
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013980 my $ObjTId1 = $CompleteSignature{1}{$Symbol}{"Class"};
13981 my $ObjTId2 = $CompleteSignature{2}{$PSymbol}{"Class"};
13982 if($ObjTId1 and $ObjTId2
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013983 and not $CompleteSignature{1}{$Symbol}{"Static"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013984 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013985 my $ThisPtr1_Id = getTypeIdByName($TypeInfo{1}{$ObjTId1}{"Name"}."*const", 1);
13986 my $ThisPtr2_Id = getTypeIdByName($TypeInfo{2}{$ObjTId2}{"Name"}."*const", 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013987 if($ThisPtr1_Id and $ThisPtr2_Id)
13988 {
13989 @RecurTypes = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013990 %SubProblems = mergeTypes($ThisPtr1_Id, $ThisPtr2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013991 foreach my $SubProblemType (keys(%SubProblems))
13992 {
13993 foreach my $SubLocation (keys(%{$SubProblems{$SubProblemType}}))
13994 {
13995 my $NewLocation = ($SubLocation)?"this->".$SubLocation:"this";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013996 %{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040013997 "Object_Type_Name"=>$TypeInfo{1}{$ObjTId1}{"Name"} );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040013998 @{$CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}}{keys(%{$SubProblems{$SubProblemType}{$SubLocation}})} = values %{$SubProblems{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040013999 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014000 $CompatProblems{$Level}{$Symbol}{$SubProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$ObjTId1}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014001 }
14002 }
14003 }
14004 }
14005 }
14006 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014007 if($Level eq "Binary") {
14008 mergeVTables($Level);
14009 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014010 foreach my $Symbol (keys(%{$CompatProblems{$Level}})) {
14011 $CheckedSymbols{$Level}{$Symbol} = 1;
14012 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014013}
14014
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014015sub rmQuals($$)
14016{
14017 my ($Value, $Qual) = @_;
14018 if(not $Qual) {
14019 return $Value;
14020 }
14021 if($Qual eq "all")
14022 { # all quals
14023 $Qual = "const|volatile|restrict";
14024 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014025 while($Value=~s/\b$Qual\b//) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014026 $Value = formatName($Value, "T");
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014027 }
14028 return $Value;
14029}
14030
14031sub cmpBTypes($$$$)
14032{
14033 my ($T1, $T2, $V1, $V2) = @_;
14034 $T1 = uncover_typedefs($T1, $V1);
14035 $T2 = uncover_typedefs($T2, $V2);
14036 return (rmQuals($T1, "all") eq rmQuals($T2, "all"));
14037}
14038
14039sub addedQual($$$)
14040{
14041 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014042 return removedQual_I($New_Value, $Old_Value, 2, 1, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014043}
14044
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014045sub removedQual($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014046{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014047 my ($Old_Value, $New_Value, $Qual) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014048 return removedQual_I($Old_Value, $New_Value, 1, 2, $Qual);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014049}
14050
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014051sub removedQual_I($$$$$)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014052{
14053 my ($Old_Value, $New_Value, $V1, $V2, $Qual) = @_;
14054 $Old_Value = uncover_typedefs($Old_Value, $V1);
14055 $New_Value = uncover_typedefs($New_Value, $V2);
14056 if($Old_Value eq $New_Value)
14057 { # equal types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014058 return 0;
14059 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014060 if($Old_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014061 { # without a qual
14062 return 0;
14063 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014064 elsif($New_Value!~/\b$Qual\b/)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014065 { # became non-qual
14066 return 1;
14067 }
14068 else
14069 {
14070 my @BQ1 = getQualModel($Old_Value, $Qual);
14071 my @BQ2 = getQualModel($New_Value, $Qual);
14072 foreach (0 .. $#BQ1)
14073 { # removed qual
14074 if($BQ1[$_]==1
14075 and $BQ2[$_]!=1)
14076 {
14077 return 2;
14078 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014079 }
14080 }
14081 return 0;
14082}
14083
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014084sub getQualModel($$)
14085{
14086 my ($Value, $Qual) = @_;
14087 if(not $Qual) {
14088 return $Value;
14089 }
14090
14091 # cleaning
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014092 while($Value=~/(\w+)/ and $1 ne $Qual) {
14093 $Value=~s/\b$1\b//g;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014094 }
14095 $Value=~s/[^\*\&\w]+//g;
14096
14097 # modeling
14098 # int*const*const == 011
14099 # int**const == 001
14100 my @Model = ();
14101 my @Elems = split(/[\*\&]/, $Value);
14102 if(not @Elems) {
14103 return (0);
14104 }
14105 foreach (@Elems)
14106 {
14107 if($_ eq $Qual) {
14108 push(@Model, 1);
14109 }
14110 else {
14111 push(@Model, 0);
14112 }
14113 }
14114
14115 return @Model;
14116}
14117
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014118my %StringTypes = map {$_=>1} (
14119 "char*",
14120 "char const*"
14121);
14122
14123my %CharTypes = map {$_=>1} (
14124 "char",
14125 "char const"
14126);
14127
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014128sub showVal($$$)
14129{
14130 my ($Value, $TypeId, $LibVersion) = @_;
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014131 my %PureType = get_PureType($TypeId, $TypeInfo{$LibVersion});
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040014132 my $TName = uncover_typedefs($PureType{"Name"}, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014133 if(substr($Value, 0, 2) eq "_Z")
14134 {
14135 if(my $Unmangled = $tr_name{$Value}) {
14136 return $Unmangled;
14137 }
14138 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014139 elsif(defined $StringTypes{$TName} or $TName=~/string/i)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014140 { # strings
14141 return "\"$Value\"";
14142 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014143 elsif(defined $CharTypes{$TName})
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014144 { # characters
14145 return "\'$Value\'";
14146 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040014147 if($Value eq "")
14148 { # other
14149 return "\'\'";
14150 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014151 return $Value;
14152}
14153
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014154sub getRegs($$$)
14155{
14156 my ($LibVersion, $Symbol, $Pos) = @_;
14157
14158 if(defined $CompleteSignature{$LibVersion}{$Symbol}{"Reg"})
14159 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014160 my %Regs = ();
14161 foreach my $Elem (sort keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}}))
14162 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014163 if($Elem=~/\A$Pos([\.\+]|\Z)/) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014164 $Regs{$CompleteSignature{$LibVersion}{$Symbol}{"Reg"}{$Elem}} = 1;
14165 }
14166 }
14167
14168 return join(", ", sort keys(%Regs));
14169 }
14170
14171 return undef;
14172}
14173
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014174sub mergeParameters($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014175{
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014176 my ($Symbol, $PSymbol, $ParamPos1, $ParamPos2, $Level, $ChkRnmd) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014177 if(not $Symbol) {
14178 return;
14179 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014180 my $PType1_Id = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"type"};
14181 my $PName1 = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"name"};
14182 my $PType2_Id = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"type"};
14183 my $PName2 = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"name"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014184 if(not $PType1_Id
14185 or not $PType2_Id) {
14186 return;
14187 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014188
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014189 if(index($Symbol, "_Z")==0)
14190 { # do not merge "this"
14191 if($PName1 eq "this" or $PName2 eq "this") {
14192 return;
14193 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014194 }
14195
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014196 my %Type1 = get_Type($PType1_Id, 1);
14197 my %Type2 = get_Type($PType2_Id, 2);
14198 my %BaseType1 = get_BaseType($PType1_Id, 1);
14199 my %BaseType2 = get_BaseType($PType2_Id, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014200 my $Parameter_Location = ($PName1)?$PName1:showPos($ParamPos1)." Parameter";
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014201
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014202 if($Level eq "Binary")
14203 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014204 if(checkDump(1, "2.6.1") and checkDump(2, "2.6.1"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014205 { # "reg" attribute added in ACC 1.95.1 (dump 2.6.1 format)
14206 if($CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14207 and not $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14208 {
14209 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Non_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014210 "Target"=>$PName1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014211 "Param_Pos"=>$ParamPos1 );
14212 }
14213 elsif(not $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"reg"}
14214 and $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"reg"})
14215 {
14216 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Became_Register"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014217 "Target"=>$PName1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014218 "Param_Pos"=>$ParamPos1 );
14219 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014220 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014221
14222 if(defined $UsedDump{1}{"DWARF"}
14223 and defined $UsedDump{2}{"DWARF"})
14224 {
14225 if(checkDump(1, "3.0") and checkDump(2, "3.0"))
14226 {
14227 my $Old_Regs = getRegs(1, $Symbol, $ParamPos1);
14228 my $New_Regs = getRegs(2, $PSymbol, $ParamPos2);
14229 if($Old_Regs and $New_Regs)
14230 {
14231 if($Old_Regs ne $New_Regs)
14232 {
14233 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Register"}{$Parameter_Location}}=(
14234 "Target"=>$PName1,
14235 "Param_Pos"=>$ParamPos1,
14236 "Old_Value"=>$Old_Regs,
14237 "New_Value"=>$New_Regs );
14238 }
14239 }
14240 elsif($Old_Regs and not $New_Regs)
14241 {
14242 %{$CompatProblems{$Level}{$Symbol}{"Parameter_From_Register"}{$Parameter_Location}}=(
14243 "Target"=>$PName1,
14244 "Param_Pos"=>$ParamPos1,
14245 "Old_Value"=>$Old_Regs );
14246 }
14247 elsif(not $Old_Regs and $New_Regs)
14248 {
14249 %{$CompatProblems{$Level}{$Symbol}{"Parameter_To_Register"}{$Parameter_Location}}=(
14250 "Target"=>$PName1,
14251 "Param_Pos"=>$ParamPos1,
14252 "New_Value"=>$New_Regs );
14253 }
14254 if((my $Old_Offset = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"offset"}) ne ""
14255 and (my $New_Offset = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"offset"}) ne "")
14256 {
14257 if($Old_Offset ne $New_Offset)
14258 {
14259 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Changed_Offset"}{$Parameter_Location}}=(
14260 "Target"=>$PName1,
14261 "Param_Pos"=>$ParamPos1,
14262 "Old_Value"=>$Old_Offset,
14263 "New_Value"=>$New_Offset );
14264 }
14265 }
14266 }
14267 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014268 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014269 if(checkDump(1, "2.0") and checkDump(2, "2.0")
14270 and $UsedDump{1}{"V"} ne "3.1" and $UsedDump{2}{"V"} ne "3.1")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014271 { # "default" attribute added in ACC 1.22 (dump 2.0 format)
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040014272 # broken in 3.1, fixed in 3.2
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014273 my $Value_Old = $CompleteSignature{1}{$Symbol}{"Param"}{$ParamPos1}{"default"};
14274 my $Value_New = $CompleteSignature{2}{$PSymbol}{"Param"}{$ParamPos2}{"default"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014275 if(not checkDump(1, "2.13")
14276 and checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014277 { # support for old ABI dumps
14278 if(defined $Value_Old and defined $Value_New)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014279 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014280 if($Type1{"Name"} eq "bool"
14281 and $Value_Old eq "false" and $Value_New eq "0")
14282 { # int class::method ( bool p = 0 );
14283 # old ABI dumps: "false"
14284 # new ABI dumps: "0"
14285 $Value_Old = "0";
14286 }
14287 }
14288 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040014289 if(not checkDump(1, "2.18")
14290 and checkDump(2, "2.18"))
14291 { # support for old ABI dumps
14292 if(not defined $Value_Old
14293 and substr($Value_New, 0, 2) eq "_Z") {
14294 $Value_Old = $Value_New;
14295 }
14296 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014297 if(defined $Value_Old)
14298 {
14299 $Value_Old = showVal($Value_Old, $PType1_Id, 1);
14300 if(defined $Value_New)
14301 {
14302 $Value_New = showVal($Value_New, $PType2_Id, 2);
14303 if($Value_Old ne $Value_New)
14304 { # FIXME: how to distinguish "0" and 0 (NULL)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014305 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Changed"}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014306 "Target"=>$PName1,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014307 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014308 "Old_Value"=>$Value_Old,
14309 "New_Value"=>$Value_New );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014310 }
14311 }
14312 else
14313 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014314 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Removed"}{$Parameter_Location}}=(
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014315 "Target"=>$PName1,
14316 "Param_Pos"=>$ParamPos1,
14317 "Old_Value"=>$Value_Old );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014318 }
14319 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014320 elsif(defined $Value_New)
14321 {
14322 $Value_New = showVal($Value_New, $PType2_Id, 2);
14323 %{$CompatProblems{$Level}{$Symbol}{"Parameter_Default_Value_Added"}{$Parameter_Location}}=(
14324 "Target"=>$PName1,
14325 "Param_Pos"=>$ParamPos1,
14326 "New_Value"=>$Value_New );
14327 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014328 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014329
14330 if($ChkRnmd)
14331 {
14332 if($PName1 and $PName2 and $PName1 ne $PName2
14333 and $PType1_Id!=-1 and $PType2_Id!=-1
14334 and $PName1!~/\Ap\d+\Z/ and $PName2!~/\Ap\d+\Z/)
14335 { # except unnamed "..." value list (Id=-1)
14336 %{$CompatProblems{$Level}{$Symbol}{"Renamed_Parameter"}{showPos($ParamPos1)." Parameter"}}=(
14337 "Target"=>$PName1,
14338 "Param_Pos"=>$ParamPos1,
14339 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
14340 "Old_Value"=>$PName1,
14341 "New_Value"=>$PName2,
14342 "New_Signature"=>get_Signature($Symbol, 2) );
14343 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014344 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040014345
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014346 # checking type change (replace)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014347 my %SubProblems = detectTypeChange($PType1_Id, $PType2_Id, "Parameter", $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014348 foreach my $SubProblemType (keys(%SubProblems))
14349 { # add new problems, remove false alarms
14350 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14351 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014352
14353 # quals
14354 if($SubProblemType eq "Parameter_Type"
14355 or $SubProblemType eq "Parameter_Type_And_Size"
14356 or $SubProblemType eq "Parameter_Type_Format")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014357 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014358 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014359 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014360 if(addedQual($Old_Value, $New_Value, "restrict")) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014361 %{$SubProblems{"Parameter_Became_Restrict"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014362 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014363 elsif(removedQual($Old_Value, $New_Value, "restrict")) {
14364 %{$SubProblems{"Parameter_Became_Non_Restrict"}} = %{$SubProblems{$SubProblemType}};
14365 }
14366 }
14367 if(checkDump(1, "2.6") and checkDump(2, "2.6"))
14368 {
14369 if(removedQual($Old_Value, $New_Value, "volatile")) {
14370 %{$SubProblems{"Parameter_Became_Non_Volatile"}} = %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014371 }
14372 }
14373 if($Type2{"Type"} eq "Const" and $BaseType2{"Name"} eq $Type1{"Name"}
14374 and $Type1{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14375 { # int to "int const"
14376 delete($SubProblems{$SubProblemType});
14377 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014378 elsif($Type1{"Type"} eq "Const" and $BaseType1{"Name"} eq $Type2{"Name"}
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014379 and $Type2{"Type"}=~/Intrinsic|Class|Struct|Union|Enum/)
14380 { # "int const" to int
14381 delete($SubProblems{$SubProblemType});
14382 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014383 elsif(my $RR = removedQual($Old_Value, $New_Value, "const"))
14384 { # "const" to non-"const"
14385 if($RR==2) {
14386 %{$SubProblems{"Parameter_Removed_Const"}} = %{$SubProblems{$SubProblemType}};
14387 }
14388 else {
14389 %{$SubProblems{"Parameter_Became_Non_Const"}} = %{$SubProblems{$SubProblemType}};
14390 }
14391 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014392 }
14393 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014394
14395 if($Level eq "Source")
14396 {
14397 foreach my $SubProblemType (keys(%SubProblems))
14398 {
14399 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14400 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
14401
14402 if($SubProblemType eq "Parameter_Type")
14403 {
14404 if(cmpBTypes($Old_Value, $New_Value, 1, 2)) {
14405 delete($SubProblems{$SubProblemType});
14406 }
14407 }
14408 }
14409 }
14410
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014411 foreach my $SubProblemType (keys(%SubProblems))
14412 { # modify/register problems
14413 my $New_Value = $SubProblems{$SubProblemType}{"New_Value"};
14414 my $Old_Value = $SubProblems{$SubProblemType}{"Old_Value"};
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014415 my $New_Size = $SubProblems{$SubProblemType}{"New_Size"};
14416 my $Old_Size = $SubProblems{$SubProblemType}{"Old_Size"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014417
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014418 my $NewProblemType = $SubProblemType;
14419 if($Old_Value eq "..." and $New_Value ne "...")
14420 { # change from "..." to "int"
14421 if($ParamPos1==0)
14422 { # ISO C requires a named argument before "..."
14423 next;
14424 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014425 $NewProblemType = "Parameter_Became_Non_VaList";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014426 }
14427 elsif($New_Value eq "..." and $Old_Value ne "...")
14428 { # change from "int" to "..."
14429 if($ParamPos2==0)
14430 { # ISO C requires a named argument before "..."
14431 next;
14432 }
14433 $NewProblemType = "Parameter_Became_VaList";
14434 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014435 elsif($Level eq "Binary" and ($SubProblemType eq "Parameter_Type_And_Size"
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014436 or $SubProblemType eq "Parameter_Type" or $SubProblemType eq "Parameter_Type_Format"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014437 {
14438 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014439 if($Arch1 eq "unknown"
14440 or $Arch2 eq "unknown")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014441 { # if one of the architectures is unknown
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014442 # then set other arhitecture to unknown too
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014443 ($Arch1, $Arch2) = ("unknown", "unknown");
14444 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014445 my (%Conv1, %Conv2) = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014446 if($UseConv_Real{1}{"P"} and $UseConv_Real{2}{"P"})
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014447 { # real
14448 %Conv1 = callingConvention_P_Real($CompleteSignature{1}{$Symbol}, $ParamPos1);
14449 %Conv2 = callingConvention_P_Real($CompleteSignature{2}{$Symbol}, $ParamPos2);
14450 }
14451 else
14452 { # model
14453 %Conv1 = callingConvention_P_Model($CompleteSignature{1}{$Symbol}, $ParamPos1, $TypeInfo{1}, $Arch1, $OStarget, $WORD_SIZE{1});
14454 %Conv2 = callingConvention_P_Model($CompleteSignature{2}{$Symbol}, $ParamPos2, $TypeInfo{2}, $Arch2, $OStarget, $WORD_SIZE{2});
14455 }
14456 if($Conv1{"Method"} eq $Conv2{"Method"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014457 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014458 if($Conv1{"Method"} eq "stack")
14459 {
14460 if($Old_Size ne $New_Size) { # FIXME: isMemPadded, getOffset
14461 $NewProblemType = "Parameter_Type_And_Stack";
14462 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014463 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014464 elsif($Conv1{"Method"} eq "reg")
14465 {
14466 if($Conv1{"Registers"} ne $Conv2{"Registers"}) {
14467 $NewProblemType = "Parameter_Type_And_Register";
14468 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014469 }
14470 }
14471 else
14472 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014473 if($Conv1{"Method"} eq "stack") {
14474 $NewProblemType = "Parameter_Type_From_Stack_To_Register";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014475 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014476 elsif($Conv1{"Method"} eq "register") {
14477 $NewProblemType = "Parameter_Type_From_Register_To_Stack";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014478 }
14479 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014480 $SubProblems{$SubProblemType}{"Old_Reg"} = $Conv1{"Registers"};
14481 $SubProblems{$SubProblemType}{"New_Reg"} = $Conv2{"Registers"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014482 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014483 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}=(
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014484 "Target"=>$PName1,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014485 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014486 "New_Signature"=>get_Signature($Symbol, 2) );
14487 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$Parameter_Location}}{keys(%{$SubProblems{$SubProblemType}})} = values %{$SubProblems{$SubProblemType}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014488 }
14489 @RecurTypes = ();
14490 # checking type definition changes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014491 my %SubProblems_Merge = mergeTypes($PType1_Id, $PType2_Id, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014492 foreach my $SubProblemType (keys(%SubProblems_Merge))
14493 {
14494 foreach my $SubLocation (keys(%{$SubProblems_Merge{$SubProblemType}}))
14495 {
14496 my $NewProblemType = $SubProblemType;
14497 if($SubProblemType eq "DataType_Size")
14498 {
14499 my $InitialType_Type = $SubProblems_Merge{$SubProblemType}{$SubLocation}{"InitialType_Type"};
14500 if($InitialType_Type!~/\A(Pointer|Ref)\Z/ and $SubLocation!~/\-\>/)
14501 { # stack has been affected
14502 $NewProblemType = "DataType_Size_And_Stack";
14503 }
14504 }
14505 my $NewLocation = ($SubLocation)?$Parameter_Location."->".$SubLocation:$Parameter_Location;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014506 %{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}}=(
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014507 "Param_Type"=>$TypeInfo{1}{$PType1_Id}{"Name"},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014508 "Param_Pos"=>$ParamPos1,
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014509 "Param_Name"=>$PName1 );
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014510 @{$CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}}{keys(%{$SubProblems_Merge{$SubProblemType}{$SubLocation}})} = values %{$SubProblems_Merge{$SubProblemType}{$SubLocation}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014511 if($SubLocation!~/\-\>/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014512 $CompatProblems{$Level}{$Symbol}{$NewProblemType}{$NewLocation}{"Start_Type_Name"} = $TypeInfo{1}{$PType1_Id}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014513 }
14514 }
14515 }
14516}
14517
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014518sub find_ParamPair_Pos_byName($$$)
14519{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014520 my ($Name, $Symbol, $LibVersion) = @_;
14521 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014522 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014523 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14524 if($CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"name"} eq $Name)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014525 {
14526 return $ParamPos;
14527 }
14528 }
14529 return "lost";
14530}
14531
14532sub find_ParamPair_Pos_byTypeAndPos($$$$$)
14533{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014534 my ($TypeName, $MediumPos, $Order, $Symbol, $LibVersion) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014535 my @Positions = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014536 foreach my $ParamPos (sort {int($a)<=>int($b)} keys(%{$CompleteSignature{$LibVersion}{$Symbol}{"Param"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014537 {
14538 next if($Order eq "backward" and $ParamPos>$MediumPos);
14539 next if($Order eq "forward" and $ParamPos<$MediumPos);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014540 next if(not defined $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos});
14541 my $PTypeId = $CompleteSignature{$LibVersion}{$Symbol}{"Param"}{$ParamPos}{"type"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014542 if($TypeInfo{$LibVersion}{$PTypeId}{"Name"} eq $TypeName) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014543 push(@Positions, $ParamPos);
14544 }
14545 }
14546 return @Positions;
14547}
14548
14549sub getTypeIdByName($$)
14550{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040014551 my ($TypeName, $LibVersion) = @_;
14552 return $TName_Tid{$LibVersion}{formatName($TypeName, "T")};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014553}
14554
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014555sub diffTypes($$$)
14556{
14557 if(defined $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]}) {
14558 return $Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]};
14559 }
14560 if(isRecurType($_[0], $_[1], \@RecurTypes_Diff))
14561 { # skip recursive declarations
14562 return 0;
14563 }
14564
14565 pushType($_[0], $_[1], \@RecurTypes_Diff);
14566 my $Diff = diffTypes_I(@_);
14567 pop(@RecurTypes_Diff);
14568
14569 return ($Cache{"diffTypes"}{$_[2]}{$_[0]}{$_[1]} = $Diff);
14570}
14571
14572sub diffTypes_I($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014573{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014574 my ($Type1_Id, $Type2_Id, $Level) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014575
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014576 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14577 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014578
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014579 if($Type1_Pure{"Name"} eq $Type2_Pure{"Name"})
14580 { # equal types
14581 return 0;
14582 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014583 if($Type1_Pure{"Name"} eq "void")
14584 { # from void* to something
14585 return 0;
14586 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014587 if($Type1_Pure{"Name"}=~/\*/
14588 or $Type2_Pure{"Name"}=~/\*/)
14589 { # compared in detectTypeChange()
14590 return 0;
14591 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014592
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014593 my %FloatType = map {$_=>1} (
14594 "float",
14595 "double",
14596 "long double"
14597 );
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014598
14599 my $T1 = $Type1_Pure{"Type"};
14600 my $T2 = $Type2_Pure{"Type"};
14601
14602 if($T1 eq "Struct"
14603 and $T2 eq "Class")
14604 { # compare as data structures
14605 $T2 = "Struct";
14606 }
14607
14608 if($T1 eq "Class"
14609 and $T2 eq "Struct")
14610 { # compare as data structures
14611 $T1 = "Struct";
14612 }
14613
14614 if($T1 ne $T2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014615 { # different types
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014616 if($T1 eq "Intrinsic"
14617 and $T2 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014618 { # "int" to "enum"
14619 return 0;
14620 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014621 elsif($T2 eq "Intrinsic"
14622 and $T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014623 { # "enum" to "int"
14624 return 0;
14625 }
14626 else
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014627 { # union to struct
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014628 # ...
14629 return 1;
14630 }
14631 }
14632 else
14633 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014634 if($T1 eq "Intrinsic")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014635 {
14636 if($FloatType{$Type1_Pure{"Name"}}
14637 or $FloatType{$Type2_Pure{"Name"}})
14638 { # "float" to "double"
14639 # "float" to "int"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014640 if($Level eq "Source")
14641 { # Safe
14642 return 0;
14643 }
14644 else {
14645 return 1;
14646 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014647 }
14648 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014649 elsif($T1=~/Class|Struct|Union|Enum/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014650 {
14651 my @Membs1 = keys(%{$Type1_Pure{"Memb"}});
14652 my @Membs2 = keys(%{$Type2_Pure{"Memb"}});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014653 if(not @Membs1
14654 or not @Membs2)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040014655 { # private
14656 return 0;
14657 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014658 if($#Membs1!=$#Membs2)
14659 { # different number of elements
14660 return 1;
14661 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014662 if($T1 eq "Enum")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014663 {
14664 foreach my $Pos (@Membs1)
14665 { # compare elements by name and value
14666 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"}
14667 or $Type1_Pure{"Memb"}{$Pos}{"value"} ne $Type2_Pure{"Memb"}{$Pos}{"value"})
14668 { # different names
14669 return 1;
14670 }
14671 }
14672 }
14673 else
14674 {
14675 foreach my $Pos (@Membs1)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014676 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014677 if($Level eq "Source")
14678 {
14679 if($Type1_Pure{"Memb"}{$Pos}{"name"} ne $Type2_Pure{"Memb"}{$Pos}{"name"})
14680 { # different names
14681 return 1;
14682 }
14683 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014684
14685 my %MT1 = %{$TypeInfo{1}{$Type1_Pure{"Memb"}{$Pos}{"type"}}};
14686 my %MT2 = %{$TypeInfo{2}{$Type2_Pure{"Memb"}{$Pos}{"type"}}};
14687
14688 if($MT1{"Name"} ne $MT2{"Name"}
14689 or isAnon($MT1{"Name"}) or isAnon($MT2{"Name"}))
14690 {
14691 my $PL1 = get_PLevel($MT1{"Tid"}, 1);
14692 my $PL2 = get_PLevel($MT2{"Tid"}, 2);
14693
14694 if($PL1 ne $PL2)
14695 { # different pointer level
14696 return 1;
14697 }
14698
14699 # compare base types
14700 my %BT1 = get_BaseType($MT1{"Tid"}, 1);
14701 my %BT2 = get_BaseType($MT2{"Tid"}, 2);
14702
14703 if(diffTypes($BT1{"Tid"}, $BT2{"Tid"}, $Level))
14704 { # different types
14705 return 1;
14706 }
14707 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014708 }
14709 }
14710 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014711 else
14712 {
14713 # TODO: arrays, etc.
14714 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014715 }
14716 return 0;
14717}
14718
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014719sub detectTypeChange($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014720{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014721 my ($Type1_Id, $Type2_Id, $Prefix, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014722 if(not $Type1_Id or not $Type2_Id) {
14723 return ();
14724 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014725 my %LocalProblems = ();
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014726 my %Type1 = get_Type($Type1_Id, 1);
14727 my %Type2 = get_Type($Type2_Id, 2);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014728 my %Type1_Pure = get_PureType($Type1_Id, $TypeInfo{1});
14729 my %Type2_Pure = get_PureType($Type2_Id, $TypeInfo{2});
14730 my %Type1_Base = ($Type1_Pure{"Type"} eq "Array")?get_OneStep_BaseType($Type1_Pure{"Tid"}, $TypeInfo{1}):get_BaseType($Type1_Id, 1);
14731 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 +040014732
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014733 my $Type1_PLevel = get_PLevel($Type1_Id, 1);
14734 my $Type2_PLevel = get_PLevel($Type2_Id, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014735 return () if(not $Type1{"Name"} or not $Type2{"Name"});
14736 return () if(not $Type1_Base{"Name"} or not $Type2_Base{"Name"});
14737 return () if($Type1_PLevel eq "" or $Type2_PLevel eq "");
14738 if($Type1_Base{"Name"} ne $Type2_Base{"Name"}
14739 and ($Type1{"Name"} eq $Type2{"Name"} or ($Type1_PLevel>=1 and $Type1_PLevel==$Type2_PLevel
14740 and $Type1_Base{"Name"} ne "void" and $Type2_Base{"Name"} ne "void")))
14741 { # base type change
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040014742 if($Type1{"Name"} eq $Type2{"Name"})
14743 {
14744 if($Type1{"Type"} eq "Typedef" and $Type2{"Type"} eq "Typedef")
14745 { # will be reported in mergeTypes() as typedef problem
14746 return ();
14747 }
14748 my %Typedef_1 = goToFirst($Type1{"Tid"}, 1, "Typedef");
14749 my %Typedef_2 = goToFirst($Type2{"Tid"}, 2, "Typedef");
14750 if(%Typedef_1 and %Typedef_2)
14751 {
14752 if($Typedef_1{"Name"} eq $Typedef_2{"Name"}
14753 and $Typedef_1{"Type"} eq "Typedef" and $Typedef_2{"Type"} eq "Typedef")
14754 { # const Typedef
14755 return ();
14756 }
14757 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014758 }
14759 if($Type1_Base{"Name"}!~/anon\-/ and $Type2_Base{"Name"}!~/anon\-/)
14760 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014761 if($Level eq "Binary"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014762 and $Type1_Base{"Size"} and $Type2_Base{"Size"}
14763 and $Type1_Base{"Size"} ne $Type2_Base{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014764 {
14765 %{$LocalProblems{$Prefix."_BaseType_And_Size"}}=(
14766 "Old_Value"=>$Type1_Base{"Name"},
14767 "New_Value"=>$Type2_Base{"Name"},
14768 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
14769 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
14770 "InitialType_Type"=>$Type1_Pure{"Type"});
14771 }
14772 else
14773 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014774 if(diffTypes($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014775 { # format change
14776 %{$LocalProblems{$Prefix."_BaseType_Format"}}=(
14777 "Old_Value"=>$Type1_Base{"Name"},
14778 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014779 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
14780 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014781 "InitialType_Type"=>$Type1_Pure{"Type"});
14782 }
14783 elsif(tNameLock($Type1_Base{"Tid"}, $Type2_Base{"Tid"}))
14784 {
14785 %{$LocalProblems{$Prefix."_BaseType"}}=(
14786 "Old_Value"=>$Type1_Base{"Name"},
14787 "New_Value"=>$Type2_Base{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014788 "Old_Size"=>$Type1_Base{"Size"}*$BYTE_SIZE,
14789 "New_Size"=>$Type2_Base{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014790 "InitialType_Type"=>$Type1_Pure{"Type"});
14791 }
14792 }
14793 }
14794 }
14795 elsif($Type1{"Name"} ne $Type2{"Name"})
14796 { # type change
14797 if($Type1{"Name"}!~/anon\-/ and $Type2{"Name"}!~/anon\-/)
14798 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014799 if($Prefix eq "Return"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014800 and $Type1_Pure{"Name"} eq "void")
14801 {
14802 %{$LocalProblems{"Return_Type_From_Void"}}=(
14803 "New_Value"=>$Type2{"Name"},
14804 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
14805 "InitialType_Type"=>$Type1_Pure{"Type"});
14806 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014807 elsif($Prefix eq "Return"
14808 and $Type2_Pure{"Name"} eq "void")
14809 {
14810 %{$LocalProblems{"Return_Type_Became_Void"}}=(
14811 "Old_Value"=>$Type1{"Name"},
14812 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14813 "InitialType_Type"=>$Type1_Pure{"Type"});
14814 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014815 else
14816 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014817 if($Level eq "Binary"
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014818 and $Type1{"Size"} and $Type2{"Size"}
14819 and $Type1{"Size"} ne $Type2{"Size"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014820 {
14821 %{$LocalProblems{$Prefix."_Type_And_Size"}}=(
14822 "Old_Value"=>$Type1{"Name"},
14823 "New_Value"=>$Type2{"Name"},
14824 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14825 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
14826 "InitialType_Type"=>$Type1_Pure{"Type"});
14827 }
14828 else
14829 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014830 if(diffTypes($Type1_Id, $Type2_Id, $Level))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014831 { # format change
14832 %{$LocalProblems{$Prefix."_Type_Format"}}=(
14833 "Old_Value"=>$Type1{"Name"},
14834 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014835 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14836 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014837 "InitialType_Type"=>$Type1_Pure{"Type"});
14838 }
14839 elsif(tNameLock($Type1_Id, $Type2_Id))
14840 { # FIXME: correct this condition
14841 %{$LocalProblems{$Prefix."_Type"}}=(
14842 "Old_Value"=>$Type1{"Name"},
14843 "New_Value"=>$Type2{"Name"},
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014844 "Old_Size"=>$Type1{"Size"}*$BYTE_SIZE,
14845 "New_Size"=>$Type2{"Size"}*$BYTE_SIZE,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014846 "InitialType_Type"=>$Type1_Pure{"Type"});
14847 }
14848 }
14849 }
14850 }
14851 }
14852 if($Type1_PLevel!=$Type2_PLevel)
14853 {
14854 if($Type1{"Name"} ne "void" and $Type1{"Name"} ne "..."
14855 and $Type2{"Name"} ne "void" and $Type2{"Name"} ne "...")
14856 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014857 if($Level eq "Source")
14858 {
14859 %{$LocalProblems{$Prefix."_PointerLevel"}}=(
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014860 "Old_Value"=>$Type1_PLevel,
14861 "New_Value"=>$Type2_PLevel);
14862 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014863 else
14864 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014865 if($Type2_PLevel>$Type1_PLevel)
14866 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014867 %{$LocalProblems{$Prefix."_PointerLevel_Increased"}}=(
14868 "Old_Value"=>$Type1_PLevel,
14869 "New_Value"=>$Type2_PLevel);
14870 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040014871 else
14872 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014873 %{$LocalProblems{$Prefix."_PointerLevel_Decreased"}}=(
14874 "Old_Value"=>$Type1_PLevel,
14875 "New_Value"=>$Type2_PLevel);
14876 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014877 }
14878 }
14879 }
14880 if($Type1_Pure{"Type"} eq "Array")
14881 { # base_type[N] -> base_type[N]
14882 # base_type: older_structure -> typedef to newer_structure
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014883 my %SubProblems = detectTypeChange($Type1_Base{"Tid"}, $Type2_Base{"Tid"}, $Prefix, $Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014884 foreach my $SubProblemType (keys(%SubProblems))
14885 {
14886 $SubProblemType=~s/_Type/_BaseType/g;
14887 next if(defined $LocalProblems{$SubProblemType});
14888 foreach my $Attr (keys(%{$SubProblems{$SubProblemType}})) {
14889 $LocalProblems{$SubProblemType}{$Attr} = $SubProblems{$SubProblemType}{$Attr};
14890 }
14891 }
14892 }
14893 return %LocalProblems;
14894}
14895
14896sub tNameLock($$)
14897{
14898 my ($Tid1, $Tid2) = @_;
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014899 my $Changed = 0;
14900 if(differentDumps("G"))
14901 { # different GCC versions
14902 $Changed = 1;
14903 }
14904 elsif(differentDumps("V"))
14905 { # different versions of ABI dumps
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014906 if(not checkDump(1, "2.20")
14907 or not checkDump(2, "2.20"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014908 { # latest names update
14909 # 2.6: added restrict qualifier
14910 # 2.13: added missed typedefs to qualified types
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014911 # 2.20: prefix for struct, union and enum types
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014912 $Changed = 1;
14913 }
14914 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014915
14916 my $TN1 = $TypeInfo{1}{$Tid1}{"Name"};
14917 my $TN2 = $TypeInfo{2}{$Tid2}{"Name"};
14918
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014919 if($Changed)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014920 { # different formats
14921 if($UseOldDumps)
14922 { # old dumps
14923 return 0;
14924 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014925
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014926 my $TT1 = $TypeInfo{1}{$Tid1}{"Type"};
14927 my $TT2 = $TypeInfo{2}{$Tid2}{"Type"};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014928
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014929 my %Base1 = get_Type($Tid1, 1);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014930 while(defined $Base1{"Type"} and $Base1{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014931 %Base1 = get_OneStep_BaseType($Base1{"Tid"}, $TypeInfo{1});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014932 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014933 my %Base2 = get_Type($Tid2, 2);
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014934 while(defined $Base2{"Type"} and $Base2{"Type"} eq "Typedef") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040014935 %Base2 = get_OneStep_BaseType($Base2{"Tid"}, $TypeInfo{2});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014936 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040014937 my $BName1 = uncover_typedefs($Base1{"Name"}, 1);
14938 my $BName2 = uncover_typedefs($Base2{"Name"}, 2);
14939 if($BName1 eq $BName2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014940 { # equal base types
14941 return 0;
14942 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014943
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014944 if(not checkDump(1, "2.13")
14945 or not checkDump(2, "2.13"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014946 { # broken array names in ABI dumps < 2.13
14947 if($TT1 eq "Array"
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014948 and $TT2 eq "Array") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014949 return 0;
14950 }
14951 }
14952
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014953 if(not checkDump(1, "2.6")
14954 or not checkDump(2, "2.6"))
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014955 { # added restrict attribute in 2.6
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040014956 if($TN1!~/\brestrict\b/
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040014957 and $TN2=~/\brestrict\b/) {
14958 return 0;
14959 }
14960 }
14961
14962 if(not checkDump(1, "2.20")
14963 or not checkDump(2, "2.20"))
14964 { # added restrict attribute in 2.6
14965 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/
14966 or $TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040014967 return 0;
14968 }
14969 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014970 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040014971 else
14972 {
14973 # typedef struct {...} type_t
14974 # typedef struct type_t {...} type_t
14975 if(index($TN1, " ".$TN2)!=-1)
14976 {
14977 if($TN1=~/\A(struct|union|enum) \Q$TN2\E\Z/) {
14978 return 0;
14979 }
14980 }
14981 if(index($TN2, " ".$TN1)!=-1)
14982 {
14983 if($TN2=~/\A(struct|union|enum) \Q$TN1\E\Z/) {
14984 return 0;
14985 }
14986 }
14987 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014988 return 1;
14989}
14990
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014991sub differentDumps($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040014992{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014993 my $Check = $_[0];
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040014994 if(defined $Cache{"differentDumps"}{$Check}) {
14995 return $Cache{"differentDumps"}{$Check};
14996 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014997 if($UsedDump{1}{"V"} and $UsedDump{2}{"V"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040014998 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040014999 if($Check eq "G")
15000 {
15001 if(getGccVersion(1) ne getGccVersion(2))
15002 { # different GCC versions
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015003 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015004 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015005 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015006 if($Check eq "V")
15007 {
15008 if(cmpVersions(formatVersion($UsedDump{1}{"V"}, 2),
15009 formatVersion($UsedDump{2}{"V"}, 2))!=0)
15010 { # different dump versions (skip micro version)
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015011 return ($Cache{"differentDumps"}{$Check}=1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015012 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015013 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015014 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040015015 return ($Cache{"differentDumps"}{$Check}=0);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015016}
15017
15018sub formatVersion($$)
15019{ # cut off version digits
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015020 my ($V, $Digits) = @_;
15021 my @Elems = split(/\./, $V);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015022 return join(".", splice(@Elems, 0, $Digits));
15023}
15024
15025sub htmlSpecChars($)
15026{
15027 my $Str = $_[0];
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015028 if(not $Str) {
15029 return $Str;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015030 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015031 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15032 $Str=~s/</&lt;/g;
15033 $Str=~s/\-\>/&#45;&gt;/g; # &minus;
15034 $Str=~s/>/&gt;/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015035 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
15036 $Str=~s/([^ ]) ([^ ])/$1\@SP\@$2/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015037 $Str=~s/ /&#160;/g; # &nbsp;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015038 $Str=~s/\@SP\@/ /g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015039 $Str=~s/\n/<br\/>/g;
15040 $Str=~s/\"/&quot;/g;
15041 $Str=~s/\'/&#39;/g;
15042 return $Str;
15043}
15044
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040015045sub xmlSpecChars($)
15046{
15047 my $Str = $_[0];
15048 if(not $Str) {
15049 return $Str;
15050 }
15051
15052 $Str=~s/\&([^#]|\Z)/&amp;$1/g;
15053 $Str=~s/</&lt;/g;
15054 $Str=~s/>/&gt;/g;
15055
15056 $Str=~s/\"/&quot;/g;
15057 $Str=~s/\'/&#39;/g;
15058
15059 return $Str;
15060}
15061
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040015062sub xmlSpecChars_R($)
15063{
15064 my $Str = $_[0];
15065 if(not $Str) {
15066 return $Str;
15067 }
15068
15069 $Str=~s/&amp;/&/g;
15070 $Str=~s/&lt;/</g;
15071 $Str=~s/&gt;/>/g;
15072
15073 $Str=~s/&quot;/"/g;
15074 $Str=~s/&#39;/'/g;
15075
15076 return $Str;
15077}
15078
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015079sub black_name($)
15080{
15081 my $Name = $_[0];
15082 return "<span class='iname_b'>".highLight_Signature($Name)."</span>";
15083}
15084
15085sub highLight_Signature($)
15086{
15087 my $Signature = $_[0];
15088 return highLight_Signature_PPos_Italic($Signature, "", 0, 0, 0);
15089}
15090
15091sub highLight_Signature_Italic_Color($)
15092{
15093 my $Signature = $_[0];
15094 return highLight_Signature_PPos_Italic($Signature, "", 1, 1, 1);
15095}
15096
15097sub separate_symbol($)
15098{
15099 my $Symbol = $_[0];
15100 my ($Name, $Spec, $Ver) = ($Symbol, "", "");
15101 if($Symbol=~/\A([^\@\$\?]+)([\@\$]+)([^\@\$]+)\Z/) {
15102 ($Name, $Spec, $Ver) = ($1, $2, $3);
15103 }
15104 return ($Name, $Spec, $Ver);
15105}
15106
15107sub cut_f_attrs($)
15108{
15109 if($_[0]=~s/(\))((| (const volatile|const|volatile))(| \[static\]))\Z/$1/) {
15110 return $2;
15111 }
15112 return "";
15113}
15114
15115sub highLight_Signature_PPos_Italic($$$$$)
15116{
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015117 my ($FullSignature, $Param_Pos, $ItalicParams, $ColorParams, $ShowReturn) = @_;
15118 $Param_Pos = "" if(not defined $Param_Pos);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015119 if($CheckObjectsOnly) {
15120 $ItalicParams=$ColorParams=0;
15121 }
15122 my ($Signature, $VersionSpec, $SymbolVersion) = separate_symbol($FullSignature);
15123 my $Return = "";
15124 if($ShowRetVal and $Signature=~s/([^:]):([^:].+?)\Z/$1/g) {
15125 $Return = $2;
15126 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015127 my $SCenter = find_center($Signature, "(");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015128 if(not $SCenter)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015129 { # global data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015130 $Signature = htmlSpecChars($Signature);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015131 $Signature=~s!(\[data\])!<span class='attr'>$1</span>!g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015132 $Signature .= (($SymbolVersion)?"<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>":"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015133 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015134 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015135 }
15136 return $Signature;
15137 }
15138 my ($Begin, $End) = (substr($Signature, 0, $SCenter), "");
15139 $Begin.=" " if($Begin!~/ \Z/);
15140 $End = cut_f_attrs($Signature);
15141 my @Parts = ();
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015142 my ($Short, $Params) = split_Signature($Signature);
15143 my @SParts = separate_Params($Params, 1, 1);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015144 foreach my $Pos (0 .. $#SParts)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015145 {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015146 my $Part = $SParts[$Pos];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015147 $Part=~s/\A\s+|\s+\Z//g;
15148 my ($Part_Styled, $ParamName) = (htmlSpecChars($Part), "");
15149 if($Part=~/\([\*]+(\w+)\)/i) {
15150 $ParamName = $1;#func-ptr
15151 }
15152 elsif($Part=~/(\w+)[\,\)]*\Z/i) {
15153 $ParamName = $1;
15154 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015155 if(not $ParamName)
15156 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015157 push(@Parts, $Part_Styled);
15158 next;
15159 }
15160 if($ItalicParams and not $TName_Tid{1}{$Part}
15161 and not $TName_Tid{2}{$Part})
15162 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015163 my $Style = "param";
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015164 if($Param_Pos ne ""
15165 and $Pos==$Param_Pos) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015166 $Style = "focus_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015167 }
15168 elsif($ColorParams) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015169 $Style = "color_p";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015170 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015171 $Part_Styled =~ s!(\W)$ParamName([\,\)]|\Z)!$1<span class=\'$Style\'>$ParamName</span>$2!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015172 }
15173 $Part_Styled=~s/,(\w)/, $1/g;
15174 push(@Parts, $Part_Styled);
15175 }
15176 if(@Parts)
15177 {
15178 foreach my $Num (0 .. $#Parts)
15179 {
15180 if($Num==$#Parts)
15181 { # add ")" to the last parameter
15182 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]." )</span>";
15183 }
15184 elsif(length($Parts[$Num])<=45) {
15185 $Parts[$Num] = "<span class='nowrap'>".$Parts[$Num]."</span>";
15186 }
15187 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015188 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;".join(" ", @Parts)."</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015189 }
15190 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015191 $Signature = htmlSpecChars($Begin)."<span class='sym_p'>(&#160;)</span>".$End;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015192 }
15193 if($Return and $ShowReturn) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015194 $Signature .= "<span class='sym_p nowrap'> &#160;<b>:</b>&#160;&#160;".htmlSpecChars($Return)."</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015195 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015196 $Signature=~s!\[\]![&#160;]!g;
15197 $Signature=~s!operator=!operator&#160;=!g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015198 $Signature=~s!(\[in-charge\]|\[not-in-charge\]|\[in-charge-deleting\]|\[static\])!<span class='attr'>$1</span>!g;
15199 if($SymbolVersion) {
15200 $Signature .= "<span class='sym_ver'>&#160;$VersionSpec&#160;$SymbolVersion</span>";
15201 }
15202 return $Signature;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015203}
15204
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015205sub split_Signature($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015206{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015207 my $Signature = $_[0];
15208 if(my $ShortName = substr($Signature, 0, find_center($Signature, "(")))
15209 {
15210 $Signature=~s/\A\Q$ShortName\E\(//g;
15211 cut_f_attrs($Signature);
15212 $Signature=~s/\)\Z//;
15213 return ($ShortName, $Signature);
15214 }
15215
15216 # error
15217 return ($Signature, "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015218}
15219
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015220sub separate_Params($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015221{
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015222 my ($Params, $Comma, $Sp) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015223 my @Parts = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015224 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
15225 my $Part = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015226 foreach my $Pos (0 .. length($Params) - 1)
15227 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015228 my $S = substr($Params, $Pos, 1);
15229 if(defined $B{$S}) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015230 $B{$S} += 1;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015231 }
15232 if($S eq "," and
15233 $B{"("}==$B{")"} and $B{"<"}==$B{">"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015234 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015235 if($Comma)
15236 { # include comma
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015237 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015238 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015239 $Part += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015240 }
15241 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015242 $Parts[$Part] .= $S;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015243 }
15244 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040015245 if(not $Sp)
15246 { # remove spaces
15247 foreach (@Parts)
15248 {
15249 s/\A //g;
15250 s/ \Z//g;
15251 }
15252 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015253 return @Parts;
15254}
15255
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015256sub find_center($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015257{
15258 my ($Sign, $Target) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015259 my %B = ( "("=>0, "<"=>0, ")"=>0, ">"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015260 my $Center = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015261 if($Sign=~s/(operator([^\w\s\(\)]+|\(\)))//g)
15262 { # operators
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015263 $Center+=length($1);
15264 }
15265 foreach my $Pos (0 .. length($Sign)-1)
15266 {
15267 my $S = substr($Sign, $Pos, 1);
15268 if($S eq $Target)
15269 {
15270 if($B{"("}==$B{")"}
15271 and $B{"<"}==$B{">"}) {
15272 return $Center;
15273 }
15274 }
15275 if(defined $B{$S}) {
15276 $B{$S}+=1;
15277 }
15278 $Center+=1;
15279 }
15280 return 0;
15281}
15282
15283sub appendFile($$)
15284{
15285 my ($Path, $Content) = @_;
15286 return if(not $Path);
15287 if(my $Dir = get_dirname($Path)) {
15288 mkpath($Dir);
15289 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015290 open(FILE, ">>", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015291 print FILE $Content;
15292 close(FILE);
15293}
15294
15295sub writeFile($$)
15296{
15297 my ($Path, $Content) = @_;
15298 return if(not $Path);
15299 if(my $Dir = get_dirname($Path)) {
15300 mkpath($Dir);
15301 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015302 open(FILE, ">", $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015303 print FILE $Content;
15304 close(FILE);
15305}
15306
15307sub readFile($)
15308{
15309 my $Path = $_[0];
15310 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015311 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015312 local $/ = undef;
15313 my $Content = <FILE>;
15314 close(FILE);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015315 if($Path!~/\.(tu|class|abi)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015316 $Content=~s/\r/\n/g;
15317 }
15318 return $Content;
15319}
15320
15321sub get_filename($)
15322{ # much faster than basename() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015323 if(defined $Cache{"get_filename"}{$_[0]}) {
15324 return $Cache{"get_filename"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015325 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015326 if($_[0] and $_[0]=~/([^\/\\]+)[\/\\]*\Z/) {
15327 return ($Cache{"get_filename"}{$_[0]}=$1);
15328 }
15329 return ($Cache{"get_filename"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015330}
15331
15332sub get_dirname($)
15333{ # much faster than dirname() from File::Basename module
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015334 if(defined $Cache{"get_dirname"}{$_[0]}) {
15335 return $Cache{"get_dirname"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015336 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015337 if($_[0] and $_[0]=~/\A(.*?)[\/\\]+[^\/\\]*[\/\\]*\Z/) {
15338 return ($Cache{"get_dirname"}{$_[0]}=$1);
15339 }
15340 return ($Cache{"get_dirname"}{$_[0]}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015341}
15342
15343sub separate_path($) {
15344 return (get_dirname($_[0]), get_filename($_[0]));
15345}
15346
15347sub esc($)
15348{
15349 my $Str = $_[0];
15350 $Str=~s/([()\[\]{}$ &'"`;,<>\+])/\\$1/g;
15351 return $Str;
15352}
15353
15354sub readLineNum($$)
15355{
15356 my ($Path, $Num) = @_;
15357 return "" if(not $Path or not -f $Path);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015358 open(FILE, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015359 foreach (1 ... $Num) {
15360 <FILE>;
15361 }
15362 my $Line = <FILE>;
15363 close(FILE);
15364 return $Line;
15365}
15366
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015367sub readAttributes($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015368{
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040015369 my ($Path, $Num) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015370 return () if(not $Path or not -f $Path);
15371 my %Attributes = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015372 if(readLineNum($Path, $Num)=~/<!--\s+(.+)\s+-->/)
15373 {
15374 foreach my $AttrVal (split(/;/, $1))
15375 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015376 if($AttrVal=~/(.+):(.+)/)
15377 {
15378 my ($Name, $Value) = ($1, $2);
15379 $Attributes{$Name} = $Value;
15380 }
15381 }
15382 }
15383 return \%Attributes;
15384}
15385
15386sub is_abs($) {
15387 return ($_[0]=~/\A(\/|\w+:[\/\\])/);
15388}
15389
15390sub get_abs_path($)
15391{ # abs_path() should NOT be called for absolute inputs
15392 # because it can change them
15393 my $Path = $_[0];
15394 if(not is_abs($Path)) {
15395 $Path = abs_path($Path);
15396 }
15397 return $Path;
15398}
15399
15400sub get_OSgroup()
15401{
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015402 my $N = $Config{"osname"};
15403 if($N=~/macos|darwin|rhapsody/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015404 return "macos";
15405 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015406 elsif($N=~/freebsd|openbsd|netbsd/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015407 return "bsd";
15408 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015409 elsif($N=~/haiku|beos/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015410 return "beos";
15411 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015412 elsif($N=~/symbian|epoc/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015413 return "symbian";
15414 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015415 elsif($N=~/win/i) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015416 return "windows";
15417 }
15418 else {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040015419 return $N;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015420 }
15421}
15422
15423sub getGccVersion($)
15424{
15425 my $LibVersion = $_[0];
15426 if($GCC_VERSION{$LibVersion})
15427 { # dump version
15428 return $GCC_VERSION{$LibVersion};
15429 }
15430 elsif($UsedDump{$LibVersion}{"V"})
15431 { # old-version dumps
15432 return "unknown";
15433 }
15434 my $GccVersion = get_dumpversion($GCC_PATH); # host version
15435 if(not $GccVersion) {
15436 return "unknown";
15437 }
15438 return $GccVersion;
15439}
15440
15441sub showArch($)
15442{
15443 my $Arch = $_[0];
15444 if($Arch eq "arm"
15445 or $Arch eq "mips") {
15446 return uc($Arch);
15447 }
15448 return $Arch;
15449}
15450
15451sub getArch($)
15452{
15453 my $LibVersion = $_[0];
15454 if($CPU_ARCH{$LibVersion})
15455 { # dump version
15456 return $CPU_ARCH{$LibVersion};
15457 }
15458 elsif($UsedDump{$LibVersion}{"V"})
15459 { # old-version dumps
15460 return "unknown";
15461 }
15462 if(defined $Cache{"getArch"}{$LibVersion}) {
15463 return $Cache{"getArch"}{$LibVersion};
15464 }
15465 my $Arch = get_dumpmachine($GCC_PATH); # host version
15466 if(not $Arch) {
15467 return "unknown";
15468 }
15469 if($Arch=~/\A([\w]{3,})(-|\Z)/) {
15470 $Arch = $1;
15471 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040015472 $Arch = "x86" if($Arch=~/\Ai[3-7]86\Z/i);
15473 $Arch = "x86_64" if($Arch=~/\Aamd64\Z/i);
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040015474 if($OSgroup eq "windows")
15475 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015476 $Arch = "x86" if($Arch=~/win32|mingw32/i);
15477 $Arch = "x86_64" if($Arch=~/win64|mingw64/i);
15478 }
15479 $Cache{"getArch"}{$LibVersion} = $Arch;
15480 return $Arch;
15481}
15482
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015483sub get_Report_Header($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015484{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015485 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015486 my $ArchInfo = " on <span style='color:Blue;'>".showArch(getArch(1))."</span>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015487 if(getArch(1) ne getArch(2)
15488 or getArch(1) eq "unknown"
15489 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015490 { # don't show architecture in the header
15491 $ArchInfo="";
15492 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015493 my $Report_Header = "<h1><span class='nowrap'>";
15494 if($Level eq "Source") {
15495 $Report_Header .= "Source compatibility";
15496 }
15497 elsif($Level eq "Binary") {
15498 $Report_Header .= "Binary compatibility";
15499 }
15500 else {
15501 $Report_Header .= "API compatibility";
15502 }
15503 $Report_Header .= " report for the <span style='color:Blue;'>$TargetLibraryFName</span> $TargetComponent</span>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015504 $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>";
15505 if($AppPath) {
15506 $Report_Header .= " <span class='nowrap'>&#160;(relating to the portability of application <span style='color:Blue;'>".get_filename($AppPath)."</span>)</span>";
15507 }
15508 $Report_Header .= "</h1>\n";
15509 return $Report_Header;
15510}
15511
15512sub get_SourceInfo()
15513{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015514 my ($CheckedHeaders, $CheckedSources, $CheckedLibs) = ("", "");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015515 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015516 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015517 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015518 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015519 $CheckedHeaders = "<a name='Headers'></a><h2>Header Files (".($#Headers+1).")</h2><hr/>\n";
15520 $CheckedHeaders .= "<div class='h_list'>\n";
15521 foreach my $Header_Path (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15522 {
15523 my $Identity = $Registered_Headers{1}{$Header_Path}{"Identity"};
15524 my $Name = get_filename($Identity);
15525 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15526 $CheckedHeaders .= $Name.$Comment."<br/>\n";
15527 }
15528 $CheckedHeaders .= "</div>\n";
15529 $CheckedHeaders .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015530 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015531
15532 if(my @Sources = keys(%{$Registered_Sources{1}}))
15533 {
15534 $CheckedSources = "<a name='Sources'></a><h2>Source Files (".($#Sources+1).")</h2><hr/>\n";
15535 $CheckedSources .= "<div class='h_list'>\n";
15536 foreach my $Header_Path (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15537 {
15538 my $Identity = $Registered_Sources{1}{$Header_Path}{"Identity"};
15539 my $Name = get_filename($Identity);
15540 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15541 $CheckedSources .= $Name.$Comment."<br/>\n";
15542 }
15543 $CheckedSources .= "</div>\n";
15544 $CheckedSources .= "<br/>$TOP_REF<br/>\n";
15545 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015546 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015547 if(not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015548 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015549 $CheckedLibs = "<a name='Libs'></a><h2>".get_ObjTitle()." (".keys(%{$Library_Symbol{1}}).")</h2><hr/>\n";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015550 $CheckedLibs .= "<div class='lib_list'>\n";
15551 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15552 {
15553 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15554 $CheckedLibs .= $Library."<br/>\n";
15555 }
15556 $CheckedLibs .= "</div>\n";
15557 $CheckedLibs .= "<br/>$TOP_REF<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015558 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015559 return $CheckedHeaders.$CheckedSources.$CheckedLibs;
15560}
15561
15562sub get_ObjTitle()
15563{
15564 if(defined $UsedDump{1}{"DWARF"}) {
15565 return "Objects";
15566 }
15567 else {
15568 return ucfirst($SLIB_TYPE)." Libraries";
15569 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015570}
15571
15572sub get_TypeProblems_Count($$$)
15573{
15574 my ($TypeChanges, $TargetPriority, $Level) = @_;
15575 my $Type_Problems_Count = 0;
15576 foreach my $Type_Name (sort keys(%{$TypeChanges}))
15577 {
15578 my %Kinds_Target = ();
15579 foreach my $Kind (keys(%{$TypeChanges->{$Type_Name}}))
15580 {
15581 foreach my $Location (keys(%{$TypeChanges->{$Type_Name}{$Kind}}))
15582 {
15583 my $Target = $TypeChanges->{$Type_Name}{$Kind}{$Location}{"Target"};
15584 my $Priority = getProblemSeverity($Level, $Kind);
15585 next if($Priority ne $TargetPriority);
15586 if($Kinds_Target{$Kind}{$Target}) {
15587 next;
15588 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015589 if(cmpSeverities($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015590 { # select a problem with the highest priority
15591 next;
15592 }
15593 $Kinds_Target{$Kind}{$Target} = 1;
15594 $Type_Problems_Count += 1;
15595 }
15596 }
15597 }
15598 return $Type_Problems_Count;
15599}
15600
15601sub get_Summary($)
15602{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015603 my $Level = $_[0];
15604 my ($Added, $Removed, $I_Problems_High, $I_Problems_Medium, $I_Problems_Low, $T_Problems_High,
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015605 $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 +040015606 %{$RESULT{$Level}} = (
15607 "Problems"=>0,
15608 "Warnings"=>0,
15609 "Affected"=>0 );
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015610 # check rules
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015611 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015612 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015613 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015614 {
15615 if(not defined $CompatRules{$Level}{$Kind})
15616 { # unknown rule
15617 if(not $UnknownRules{$Level}{$Kind})
15618 { # only one warning
15619 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15620 $UnknownRules{$Level}{$Kind}=1;
15621 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015622 delete($CompatProblems{$Level}{$Interface}{$Kind});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015623 }
15624 }
15625 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015626 foreach my $Constant (sort keys(%{$CompatProblems_Constants{$Level}}))
15627 {
15628 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
15629 {
15630 if(not defined $CompatRules{$Level}{$Kind})
15631 { # unknown rule
15632 if(not $UnknownRules{$Level}{$Kind})
15633 { # only one warning
15634 printMsg("WARNING", "unknown rule \"$Kind\" (\"$Level\")");
15635 $UnknownRules{$Level}{$Kind}=1;
15636 }
15637 delete($CompatProblems_Constants{$Level}{$Constant}{$Kind});
15638 }
15639 }
15640 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015641 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015642 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015643 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015644 {
15645 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols")
15646 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015647 foreach my $Location (sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015648 {
15649 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015650 if($Kind eq "Added_Symbol") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015651 $Added += 1;
15652 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015653 elsif($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015654 {
15655 $Removed += 1;
15656 $TotalAffected{$Level}{$Interface} = $Priority;
15657 }
15658 else
15659 {
15660 if($Priority eq "Safe") {
15661 $I_Other += 1;
15662 }
15663 elsif($Priority eq "High") {
15664 $I_Problems_High += 1;
15665 }
15666 elsif($Priority eq "Medium") {
15667 $I_Problems_Medium += 1;
15668 }
15669 elsif($Priority eq "Low") {
15670 $I_Problems_Low += 1;
15671 }
15672 if(($Priority ne "Low" or $StrictCompat)
15673 and $Priority ne "Safe") {
15674 $TotalAffected{$Level}{$Interface} = $Priority;
15675 }
15676 }
15677 }
15678 }
15679 }
15680 }
15681 my %TypeChanges = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015682 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015683 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015684 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015685 {
15686 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
15687 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015688 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015689 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015690 my $Type_Name = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
15691 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015692 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015693 if(cmpSeverities($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015694 { # select a problem with the highest priority
15695 next;
15696 }
15697 if(($Priority ne "Low" or $StrictCompat)
15698 and $Priority ne "Safe") {
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015699 $TotalAffected{$Level}{$Interface} = maxSeverity($TotalAffected{$Level}{$Interface}, $Priority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015700 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015701 %{$TypeChanges{$Type_Name}{$Kind}{$Location}} = %{$CompatProblems{$Level}{$Interface}{$Kind}{$Location}};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040015702 $Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target} = maxSeverity($Type_MaxSeverity{$Level}{$Type_Name}{$Kind}{$Target}, $Priority);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015703 }
15704 }
15705 }
15706 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015707
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015708 $T_Problems_High = get_TypeProblems_Count(\%TypeChanges, "High", $Level);
15709 $T_Problems_Medium = get_TypeProblems_Count(\%TypeChanges, "Medium", $Level);
15710 $T_Problems_Low = get_TypeProblems_Count(\%TypeChanges, "Low", $Level);
15711 $T_Other = get_TypeProblems_Count(\%TypeChanges, "Safe", $Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015712
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015713 if($CheckObjectsOnly)
15714 { # only removed exported symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015715 $RESULT{$Level}{"Affected"} = $Removed*100/keys(%{$Symbol_Library{1}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015716 }
15717 else
15718 { # changed and removed public symbols
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015719 my $SCount = keys(%{$CheckedSymbols{$Level}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015720 if($ExtendedCheck)
15721 { # don't count external_func_0 for constants
15722 $SCount-=1;
15723 }
15724 if($SCount)
15725 {
15726 my %Weight = (
15727 "High" => 100,
15728 "Medium" => 50,
15729 "Low" => 25
15730 );
15731 foreach (keys(%{$TotalAffected{$Level}})) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015732 $RESULT{$Level}{"Affected"}+=$Weight{$TotalAffected{$Level}{$_}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015733 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015734 $RESULT{$Level}{"Affected"} = $RESULT{$Level}{"Affected"}/$SCount;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015735 }
15736 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015737 $RESULT{$Level}{"Affected"} = 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015738 }
15739 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015740 $RESULT{$Level}{"Affected"} = show_number($RESULT{$Level}{"Affected"});
15741 if($RESULT{$Level}{"Affected"}>=100) {
15742 $RESULT{$Level}{"Affected"} = 100;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015743 }
15744
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015745 $RESULT{$Level}{"Problems"} += $Removed;
15746 $RESULT{$Level}{"Problems"} += $T_Problems_High + $I_Problems_High;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015747 $RESULT{$Level}{"Problems"} += $T_Problems_Medium + $I_Problems_Medium;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015748 if($StrictCompat) {
15749 $RESULT{$Level}{"Problems"} += $T_Problems_Low + $I_Problems_Low;
15750 }
15751 else {
15752 $RESULT{$Level}{"Warnings"} += $T_Problems_Low + $I_Problems_Low;
15753 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015754
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015755 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015756 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015757 foreach my $Kind (keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015758 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015759 my $Severity = getProblemSeverity($Level, $Kind);
15760 if($Severity eq "Safe")
15761 {
15762 $C_Other+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015763 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015764 elsif($Severity eq "Low")
15765 {
15766 $C_Problems_Low+=1;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015767 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015768 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015769 }
15770
15771 if($C_Problems_Low)
15772 {
15773 if($StrictCompat) {
15774 $RESULT{$Level}{"Problems"} += $C_Problems_Low;
15775 }
15776 else {
15777 $RESULT{$Level}{"Warnings"} += $C_Problems_Low;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015778 }
15779 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015780 if($CheckImpl and $Level eq "Binary")
15781 {
15782 if($StrictCompat) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015783 $RESULT{$Level}{"Problems"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015784 }
15785 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015786 $RESULT{$Level}{"Warnings"} += keys(%CompatProblems_Impl);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015787 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015788 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015789 if($RESULT{$Level}{"Problems"}
15790 and $RESULT{$Level}{"Affected"}) {
15791 $RESULT{$Level}{"Verdict"} = "incompatible";
15792 }
15793 else {
15794 $RESULT{$Level}{"Verdict"} = "compatible";
15795 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015796
15797 my $TotalTypes = keys(%{$CheckedTypes{$Level}});
15798 if(not $TotalTypes)
15799 { # list all the types
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015800 $TotalTypes = keys(%{$TName_Tid{1}});
15801 }
15802
15803 my ($Arch1, $Arch2) = (getArch(1), getArch(2));
15804 my ($GccV1, $GccV2) = (getGccVersion(1), getGccVersion(2));
15805
15806 my ($TestInfo, $TestResults, $Problem_Summary) = ();
15807
15808 if($ReportFormat eq "xml")
15809 { # XML
15810 # test info
15811 $TestInfo .= " <library>$TargetLibraryName</library>\n";
15812 $TestInfo .= " <version1>\n";
15813 $TestInfo .= " <number>".$Descriptor{1}{"Version"}."</number>\n";
15814 $TestInfo .= " <architecture>$Arch1</architecture>\n";
15815 $TestInfo .= " <gcc>$GccV1</gcc>\n";
15816 $TestInfo .= " </version1>\n";
15817
15818 $TestInfo .= " <version2>\n";
15819 $TestInfo .= " <number>".$Descriptor{2}{"Version"}."</number>\n";
15820 $TestInfo .= " <architecture>$Arch2</architecture>\n";
15821 $TestInfo .= " <gcc>$GccV2</gcc>\n";
15822 $TestInfo .= " </version2>\n";
15823 $TestInfo = "<test_info>\n".$TestInfo."</test_info>\n\n";
15824
15825 # test results
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015826 if(my @Headers = keys(%{$Registered_Headers{1}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015827 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015828 $TestResults .= " <headers>\n";
15829 foreach my $Name (sort {lc($Registered_Headers{1}{$a}{"Identity"}) cmp lc($Registered_Headers{1}{$b}{"Identity"})} @Headers)
15830 {
15831 my $Identity = $Registered_Headers{1}{$Name}{"Identity"};
15832 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15833 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15834 }
15835 $TestResults .= " </headers>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015836 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015837
15838 if(my @Sources = keys(%{$Registered_Sources{1}}))
15839 {
15840 $TestResults .= " <sources>\n";
15841 foreach my $Name (sort {lc($Registered_Sources{1}{$a}{"Identity"}) cmp lc($Registered_Sources{1}{$b}{"Identity"})} @Sources)
15842 {
15843 my $Identity = $Registered_Sources{1}{$Name}{"Identity"};
15844 my $Comment = ($Identity=~/[\/\\]/)?" ($Identity)":"";
15845 $TestResults .= " <name>".get_filename($Name).$Comment."</name>\n";
15846 }
15847 $TestResults .= " </sources>\n";
15848 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015849
15850 $TestResults .= " <libs>\n";
15851 foreach my $Library (sort {lc($a) cmp lc($b)} keys(%{$Library_Symbol{1}}))
15852 {
15853 $Library.=" (.$LIB_EXT)" if($Library!~/\.\w+\Z/);
15854 $TestResults .= " <name>$Library</name>\n";
15855 }
15856 $TestResults .= " </libs>\n";
15857
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015858 $TestResults .= " <symbols>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))."</symbols>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015859 $TestResults .= " <types>".$TotalTypes."</types>\n";
15860
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015861 $TestResults .= " <verdict>".$RESULT{$Level}{"Verdict"}."</verdict>\n";
15862 $TestResults .= " <affected>".$RESULT{$Level}{"Affected"}."</affected>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015863 $TestResults = "<test_results>\n".$TestResults."</test_results>\n\n";
15864
15865 # problem summary
15866 $Problem_Summary .= " <added_symbols>".$Added."</added_symbols>\n";
15867 $Problem_Summary .= " <removed_symbols>".$Removed."</removed_symbols>\n";
15868
15869 $Problem_Summary .= " <problems_with_types>\n";
15870 $Problem_Summary .= " <high>$T_Problems_High</high>\n";
15871 $Problem_Summary .= " <medium>$T_Problems_Medium</medium>\n";
15872 $Problem_Summary .= " <low>$T_Problems_Low</low>\n";
15873 $Problem_Summary .= " <safe>$T_Other</safe>\n";
15874 $Problem_Summary .= " </problems_with_types>\n";
15875
15876 $Problem_Summary .= " <problems_with_symbols>\n";
15877 $Problem_Summary .= " <high>$I_Problems_High</high>\n";
15878 $Problem_Summary .= " <medium>$I_Problems_Medium</medium>\n";
15879 $Problem_Summary .= " <low>$I_Problems_Low</low>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015880 $Problem_Summary .= " <safe>$I_Other</safe>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015881 $Problem_Summary .= " </problems_with_symbols>\n";
15882
15883 $Problem_Summary .= " <problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015884 $Problem_Summary .= " <low>$C_Problems_Low</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015885 $Problem_Summary .= " </problems_with_constants>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015886 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015887 {
15888 $Problem_Summary .= " <impl>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040015889 $Problem_Summary .= " <low>".keys(%CompatProblems_Impl)."</low>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015890 $Problem_Summary .= " </impl>\n";
15891 }
15892 $Problem_Summary = "<problem_summary>\n".$Problem_Summary."</problem_summary>\n\n";
15893
15894 return ($TestInfo.$TestResults.$Problem_Summary, "");
15895 }
15896 else
15897 { # HTML
15898 # test info
15899 $TestInfo = "<h2>Test Info</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015900 $TestInfo .= "<table class='summary'>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015901 $TestInfo .= "<tr><th>".ucfirst($TargetComponent)." Name</th><td>$TargetLibraryFName</td></tr>\n";
15902
15903 my (@VInf1, @VInf2, $AddTestInfo) = ();
15904 if($Arch1 ne "unknown"
15905 and $Arch2 ne "unknown")
15906 { # CPU arch
15907 if($Arch1 eq $Arch2)
15908 { # go to the separate section
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015909 $AddTestInfo .= "<tr><th>CPU Type</th><td>".showArch($Arch1)."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015910 }
15911 else
15912 { # go to the version number
15913 push(@VInf1, showArch($Arch1));
15914 push(@VInf2, showArch($Arch2));
15915 }
15916 }
15917 if($GccV1 ne "unknown"
15918 and $GccV2 ne "unknown"
15919 and $OStarget ne "windows")
15920 { # GCC version
15921 if($GccV1 eq $GccV2)
15922 { # go to the separate section
15923 $AddTestInfo .= "<tr><th>GCC Version</th><td>$GccV1</td></tr>\n";
15924 }
15925 else
15926 { # go to the version number
15927 push(@VInf1, "gcc ".$GccV1);
15928 push(@VInf2, "gcc ".$GccV2);
15929 }
15930 }
15931 # show long version names with GCC version and CPU architecture name (if different)
15932 $TestInfo .= "<tr><th>Version #1</th><td>".$Descriptor{1}{"Version"}.(@VInf1?" (".join(", ", reverse(@VInf1)).")":"")."</td></tr>\n";
15933 $TestInfo .= "<tr><th>Version #2</th><td>".$Descriptor{2}{"Version"}.(@VInf2?" (".join(", ", reverse(@VInf2)).")":"")."</td></tr>\n";
15934 $TestInfo .= $AddTestInfo;
15935 #if($COMMON_LANGUAGE{1}) {
15936 # $TestInfo .= "<tr><th>Language</th><td>".$COMMON_LANGUAGE{1}."</td></tr>\n";
15937 #}
15938 if($ExtendedCheck) {
15939 $TestInfo .= "<tr><th>Mode</th><td>Extended</td></tr>\n";
15940 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015941 if($JoinReport)
15942 {
15943 if($Level eq "Binary") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015944 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Binary Compatibility</td></tr>\n"; # Run-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015945 }
15946 if($Level eq "Source") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015947 $TestInfo .= "<tr><th>Subject</th><td width='150px'>Source Compatibility</td></tr>\n"; # Build-time
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015948 }
15949 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015950 $TestInfo .= "</table>\n";
15951
15952 # test results
15953 $TestResults = "<h2>Test Results</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015954 $TestResults .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015955
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040015956 if(my @Headers = keys(%{$Registered_Headers{1}}))
15957 {
15958 my $Headers_Link = "<a href='#Headers' style='color:Blue;'>".($#Headers + 1)."</a>";
15959 $TestResults .= "<tr><th>Total Header Files</th><td>".$Headers_Link."</td></tr>\n";
15960 }
15961 elsif($CheckObjectsOnly) {
15962 $TestResults .= "<tr><th>Total Header Files</th><td>0&#160;(not&#160;analyzed)</td></tr>\n";
15963 }
15964
15965 if(my @Sources = keys(%{$Registered_Sources{1}}))
15966 {
15967 my $Src_Link = "<a href='#Sources' style='color:Blue;'>".($#Sources + 1)."</a>";
15968 $TestResults .= "<tr><th>Total Source Files</th><td>".$Src_Link."</td></tr>\n";
15969 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015970
15971 if(not $ExtendedCheck)
15972 {
15973 my $Libs_Link = "0";
15974 $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 +040015975 $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 +040015976 }
15977
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040015978 $TestResults .= "<tr><th>Total Symbols / Types</th><td>".(keys(%{$CheckedSymbols{$Level}}) - keys(%ExtendedSymbols))." / ".$TotalTypes."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015979
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015980 my $META_DATA = "verdict:".$RESULT{$Level}{"Verdict"}.";";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015981 if($JoinReport) {
15982 $META_DATA = "kind:".lc($Level).";".$META_DATA;
15983 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015984 $TestResults .= "<tr><th>Verdict</th>";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040015985 if($RESULT{$Level}{"Verdict"} eq "incompatible") {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040015986 $TestResults .= "<td><span style='color:Red;'><b>Incompatible<br/>(".$RESULT{$Level}{"Affected"}."%)</b></span></td>";
15987 }
15988 else {
15989 $TestResults .= "<td><span style='color:Green;'><b>Compatible</b></span></td>";
15990 }
15991 $TestResults .= "</tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015992 $TestResults .= "</table>\n";
15993
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015994 $META_DATA .= "affected:".$RESULT{$Level}{"Affected"}.";";# in percents
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015995 # problem summary
15996 $Problem_Summary = "<h2>Problem Summary</h2><hr/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040015997 $Problem_Summary .= "<table class='summary'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040015998 $Problem_Summary .= "<tr><th></th><th style='text-align:center;'>Severity</th><th style='text-align:center;'>Count</th></tr>";
15999
16000 my $Added_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016001 if($Added>0)
16002 {
16003 if($JoinReport) {
16004 $Added_Link = "<a href='#".$Level."_Added' style='color:Blue;'>$Added</a>";
16005 }
16006 else {
16007 $Added_Link = "<a href='#Added' style='color:Blue;'>$Added</a>";
16008 }
16009 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016010 $META_DATA .= "added:$Added;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016011 $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 +040016012
16013 my $Removed_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016014 if($Removed>0)
16015 {
16016 if($JoinReport) {
16017 $Removed_Link = "<a href='#".$Level."_Removed' style='color:Blue;'>$Removed</a>"
16018 }
16019 else {
16020 $Removed_Link = "<a href='#Removed' style='color:Blue;'>$Removed</a>"
16021 }
16022 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016023 $META_DATA .= "removed:$Removed;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016024 $Problem_Summary .= "<tr><th>Removed Symbols</th>";
16025 $Problem_Summary .= "<td>High</td><td".getStyle("I", "R", $Removed).">$Removed_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016026
16027 my $TH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016028 $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 +040016029 $TH_Link = "n/a" if($CheckObjectsOnly);
16030 $META_DATA .= "type_problems_high:$T_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016031 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Data Types</th>";
16032 $Problem_Summary .= "<td>High</td><td".getStyle("T", "H", $T_Problems_High).">$TH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016033
16034 my $TM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016035 $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 +040016036 $TM_Link = "n/a" if($CheckObjectsOnly);
16037 $META_DATA .= "type_problems_medium:$T_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016038 $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 +040016039
16040 my $TL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016041 $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 +040016042 $TL_Link = "n/a" if($CheckObjectsOnly);
16043 $META_DATA .= "type_problems_low:$T_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016044 $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 +040016045
16046 my $IH_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016047 $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 +040016048 $IH_Link = "n/a" if($CheckObjectsOnly);
16049 $META_DATA .= "interface_problems_high:$I_Problems_High;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016050 $Problem_Summary .= "<tr><th rowspan='3'>Problems with<br/>Symbols</th>";
16051 $Problem_Summary .= "<td>High</td><td".getStyle("I", "H", $I_Problems_High).">$IH_Link</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016052
16053 my $IM_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016054 $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 +040016055 $IM_Link = "n/a" if($CheckObjectsOnly);
16056 $META_DATA .= "interface_problems_medium:$I_Problems_Medium;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016057 $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 +040016058
16059 my $IL_Link = "0";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016060 $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 +040016061 $IL_Link = "n/a" if($CheckObjectsOnly);
16062 $META_DATA .= "interface_problems_low:$I_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016063 $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 +040016064
16065 my $ChangedConstants_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016066 if(keys(%{$CheckedSymbols{$Level}}) and $C_Problems_Low) {
16067 $ChangedConstants_Link = "<a href='#".get_Anchor("Constant", $Level, "Low")."' style='color:Blue;'>$C_Problems_Low</a>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016068 }
16069 $ChangedConstants_Link = "n/a" if($CheckObjectsOnly);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016070 $META_DATA .= "changed_constants:$C_Problems_Low;";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016071 $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 +040016072
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016073 if($CheckImpl and $Level eq "Binary")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016074 {
16075 my $ChangedImpl_Link = "0";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016076 $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 +040016077 $ChangedImpl_Link = "n/a" if($CheckHeadersOnly);
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016078 $META_DATA .= "changed_implementation:".keys(%CompatProblems_Impl).";";
16079 $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 +040016080 }
16081 # Safe Changes
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016082 if($T_Other and not $CheckObjectsOnly)
16083 {
16084 my $TS_Link = "<a href='#".get_Anchor("Type", $Level, "Safe")."' style='color:Blue;'>$T_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016085 $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 +040016086 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016087
16088 if($I_Other and not $CheckObjectsOnly)
16089 {
16090 my $IS_Link = "<a href='#".get_Anchor("Symbol", $Level, "Safe")."' style='color:Blue;'>$I_Other</a>";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016091 $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 +040016092 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016093
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016094 if($C_Other and not $CheckObjectsOnly)
16095 {
16096 my $CS_Link = "<a href='#".get_Anchor("Constant", $Level, "Safe")."' style='color:Blue;'>$C_Other</a>";
16097 $Problem_Summary .= "<tr><th>Other Changes<br/>in Constants</th><td>-</td><td".getStyle("C", "S", $C_Other).">$CS_Link</td></tr>\n";
16098 }
16099
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016100 $META_DATA .= "tool_version:$TOOL_VERSION";
16101 $Problem_Summary .= "</table>\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016102 # $TestInfo = getLegend().$TestInfo;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016103 return ($TestInfo.$TestResults.$Problem_Summary, $META_DATA);
16104 }
16105}
16106
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016107sub getStyle($$$)
16108{
16109 my ($Subj, $Act, $Num) = @_;
16110 my %Style = (
16111 "A"=>"new",
16112 "R"=>"failed",
16113 "S"=>"passed",
16114 "L"=>"warning",
16115 "M"=>"failed",
16116 "H"=>"failed"
16117 );
16118 if($Num>0) {
16119 return " class='".$Style{$Act}."'";
16120 }
16121 return "";
16122}
16123
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016124sub show_number($)
16125{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016126 if($_[0])
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016127 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016128 my $Num = cut_off_number($_[0], 2, 0);
16129 if($Num eq "0")
16130 {
16131 foreach my $P (3 .. 7)
16132 {
16133 $Num = cut_off_number($_[0], $P, 1);
16134 if($Num ne "0") {
16135 last;
16136 }
16137 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016138 }
16139 if($Num eq "0") {
16140 $Num = $_[0];
16141 }
16142 return $Num;
16143 }
16144 return $_[0];
16145}
16146
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016147sub cut_off_number($$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016148{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016149 my ($num, $digs_to_cut, $z) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016150 if($num!~/\./)
16151 {
16152 $num .= ".";
16153 foreach (1 .. $digs_to_cut-1) {
16154 $num .= "0";
16155 }
16156 }
16157 elsif($num=~/\.(.+)\Z/ and length($1)<$digs_to_cut-1)
16158 {
16159 foreach (1 .. $digs_to_cut - 1 - length($1)) {
16160 $num .= "0";
16161 }
16162 }
16163 elsif($num=~/\d+\.(\d){$digs_to_cut,}/) {
16164 $num=sprintf("%.".($digs_to_cut-1)."f", $num);
16165 }
16166 $num=~s/\.[0]+\Z//g;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016167 if($z) {
16168 $num=~s/(\.[1-9]+)[0]+\Z/$1/g;
16169 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016170 return $num;
16171}
16172
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016173sub get_Report_ChangedConstants($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016174{
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016175 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016176 my $CHANGED_CONSTANTS = "";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016177
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016178 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016179 foreach my $Constant (keys(%{$CompatProblems_Constants{$Level}}))
16180 {
16181 my $Header = $Constants{1}{$Constant}{"Header"};
16182 if(not $Header)
16183 { # added
16184 $Header = $Constants{2}{$Constant}{"Header"}
16185 }
16186
16187 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$CompatProblems_Constants{$Level}{$Constant}}))
16188 {
16189 if(not defined $CompatRules{$Level}{$Kind}) {
16190 next;
16191 }
16192 if($TargetSeverity ne getProblemSeverity($Level, $Kind)) {
16193 next;
16194 }
16195 $ReportMap{$Header}{$Constant}{$Kind} = 1;
16196 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016197 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016198
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016199 if($ReportFormat eq "xml")
16200 { # XML
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016201 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016202 {
16203 $CHANGED_CONSTANTS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016204 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016205 {
16206 $CHANGED_CONSTANTS .= " <constant name=\"$Constant\">\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016207 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16208 {
16209 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16210 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16211 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016212
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016213 $CHANGED_CONSTANTS .= " <problem id=\"$Kind\">\n";
16214 $CHANGED_CONSTANTS .= " <change".getXmlParams($Change, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Change</change>\n";
16215 $CHANGED_CONSTANTS .= " <effect".getXmlParams($Effect, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Effect</effect>\n";
16216 $CHANGED_CONSTANTS .= " <overcome".getXmlParams($Overcome, $CompatProblems_Constants{$Level}{$Constant}{$Kind}).">$Overcome</overcome>\n";
16217 $CHANGED_CONSTANTS .= " </problem>\n";
16218 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016219 $CHANGED_CONSTANTS .= " </constant>\n";
16220 }
16221 $CHANGED_CONSTANTS .= " </header>\n";
16222 }
16223 $CHANGED_CONSTANTS = "<problems_with_constants severity=\"Low\">\n".$CHANGED_CONSTANTS."</problems_with_constants>\n\n";
16224 }
16225 else
16226 { # HTML
16227 my $Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016228 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016229 {
16230 $CHANGED_CONSTANTS .= "<span class='h_name'>$HeaderName</span><br/>\n";
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016231 foreach my $Constant (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016232 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016233 my $Report = "";
16234
16235 foreach my $Kind (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}{$Constant}}))
16236 {
16237 my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, $CompatProblems_Constants{$Level}{$Constant}{$Kind});
16238 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16239 $Report .= "<tr><th>1</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16240 $Number += 1;
16241 }
16242 if($Report)
16243 {
16244 $Report = $ContentDivStart."<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>".$Report."</table><br/>$ContentDivEnd\n";
16245 $Report = $ContentSpanStart."<span class='extendable'>[+]</span> ".$Constant.$ContentSpanEnd."<br/>\n".$Report;
16246 $Report = insertIDs($Report);
16247 }
16248 $CHANGED_CONSTANTS .= $Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016249 }
16250 $CHANGED_CONSTANTS .= "<br/>\n";
16251 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016252 if($CHANGED_CONSTANTS)
16253 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016254 my $Title = "Problems with Constants, $TargetSeverity Severity";
16255 if($TargetSeverity eq "Safe")
16256 { # Safe Changes
16257 $Title = "Other Changes in Constants";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016258 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016259 $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 +040016260 }
16261 }
16262 return $CHANGED_CONSTANTS;
16263}
16264
16265sub get_Report_Impl()
16266{
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016267 my $CHANGED_IMPLEMENTATION = "";
16268 my %ReportMap = ();
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016269 foreach my $Interface (sort keys(%CompatProblems_Impl))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016270 {
16271 my $HeaderName = $CompleteSignature{1}{$Interface}{"Header"};
16272 my $DyLib = $Symbol_Library{1}{$Interface};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016273 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016274 }
16275 my $Changed_Number = 0;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016276 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016277 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016278 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016279 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016280 my %NameSpaceSymbols = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016281 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016282 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016283 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016284 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016285 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016286 $CHANGED_IMPLEMENTATION .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016287 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016288 foreach my $Interface (@SortedInterfaces)
16289 {
16290 $Changed_Number += 1;
16291 my $Signature = get_Signature($Interface, 1);
16292 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016293 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016294 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016295 $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 +040016296 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016297 $CHANGED_IMPLEMENTATION .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016298 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016299 }
16300 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016301 if($CHANGED_IMPLEMENTATION)
16302 {
16303 $CHANGED_IMPLEMENTATION = insertIDs($CHANGED_IMPLEMENTATION);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016304 $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 +040016305 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016306
16307 # clean memory
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040016308 %CompatProblems_Impl = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016309
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016310 return $CHANGED_IMPLEMENTATION;
16311}
16312
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016313sub getTitle($$$)
16314{
16315 my ($Header, $Library, $NameSpace) = @_;
16316 my $Title = "";
16317 if($Library and $Library!~/\.\w+\Z/) {
16318 $Library .= " (.$LIB_EXT)";
16319 }
16320 if($Header and $Library)
16321 {
16322 $Title .= "<span class='h_name'>$Header</span>";
16323 $Title .= ", <span class='lib_name'>$Library</span><br/>\n";
16324 }
16325 elsif($Library) {
16326 $Title .= "<span class='lib_name'>$Library</span><br/>\n";
16327 }
16328 elsif($Header) {
16329 $Title .= "<span class='h_name'>$Header</span><br/>\n";
16330 }
16331 if($NameSpace) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016332 $Title .= "<span class='ns'>namespace <b>$NameSpace</b></span><br/>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016333 }
16334 return $Title;
16335}
16336
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016337sub get_Report_Added($)
16338{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016339 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016340 my $ADDED_INTERFACES = "";
16341 my %ReportMap = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016342 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016343 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016344 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016345 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016346 if($Kind eq "Added_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016347 {
16348 my $HeaderName = $CompleteSignature{2}{$Interface}{"Header"};
16349 my $DyLib = $Symbol_Library{2}{$Interface};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016350 if($Level eq "Source" and $ReportFormat eq "html")
16351 { # do not show library name in HTML report
16352 $DyLib = "";
16353 }
16354 $ReportMap{$HeaderName}{$DyLib}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016355 }
16356 }
16357 }
16358 if($ReportFormat eq "xml")
16359 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016360 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016361 {
16362 $ADDED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016363 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016364 {
16365 $ADDED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016366 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016367 $ADDED_INTERFACES .= " <name>$Interface</name>\n";
16368 }
16369 $ADDED_INTERFACES .= " </library>\n";
16370 }
16371 $ADDED_INTERFACES .= " </header>\n";
16372 }
16373 $ADDED_INTERFACES = "<added_symbols>\n".$ADDED_INTERFACES."</added_symbols>\n\n";
16374 }
16375 else
16376 { # HTML
16377 my $Added_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016378 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016379 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016380 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016381 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016382 my %NameSpaceSymbols = ();
16383 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016384 $NameSpaceSymbols{select_Symbol_NS($Interface, 2)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016385 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016386 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016387 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016388 $ADDED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16389 my @SortedInterfaces = sort {lc(get_Signature($a, 2)) cmp lc(get_Signature($b, 2))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016390 foreach my $Interface (@SortedInterfaces)
16391 {
16392 $Added_Number += 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016393 my $Signature = get_Signature($Interface, 2);
16394 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016395 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016396 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016397 if($Interface=~/\A(_Z|\?)/)
16398 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016399 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016400 $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 +040016401 }
16402 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016403 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016404 }
16405 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040016406 else
16407 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016408 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016409 $ADDED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016410 }
16411 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016412 $ADDED_INTERFACES .= "<span class=\"iname\">".$Interface."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016413 }
16414 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016415 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016416 $ADDED_INTERFACES .= "<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016417 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016418 }
16419 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016420 if($ADDED_INTERFACES)
16421 {
16422 my $Anchor = "<a name='Added'></a>";
16423 if($JoinReport) {
16424 $Anchor = "<a name='".$Level."_Added'></a>";
16425 }
16426 $ADDED_INTERFACES = $Anchor."<h2>Added Symbols ($Added_Number)</h2><hr/>\n".$ADDED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016427 }
16428 }
16429 return $ADDED_INTERFACES;
16430}
16431
16432sub get_Report_Removed($)
16433{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016434 my $Level = $_[0];
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016435 my $REMOVED_INTERFACES = "";
16436 my %ReportMap = ();
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016437 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016438 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016439 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016440 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016441 if($Kind eq "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016442 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016443 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16444 my $DyLib = $Symbol_Library{1}{$Symbol};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016445 if($Level eq "Source" and $ReportFormat eq "html")
16446 { # do not show library name in HTML report
16447 $DyLib = "";
16448 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016449 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016450 }
16451 }
16452 }
16453 if($ReportFormat eq "xml")
16454 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016455 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016456 {
16457 $REMOVED_INTERFACES .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016458 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016459 {
16460 $REMOVED_INTERFACES .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016461 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
16462 $REMOVED_INTERFACES .= " <name>$Symbol</name>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016463 }
16464 $REMOVED_INTERFACES .= " </library>\n";
16465 }
16466 $REMOVED_INTERFACES .= " </header>\n";
16467 }
16468 $REMOVED_INTERFACES = "<removed_symbols>\n".$REMOVED_INTERFACES."</removed_symbols>\n\n";
16469 }
16470 else
16471 { # HTML
16472 my $Removed_Number = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016473 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016474 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016475 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016476 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016477 my %NameSpaceSymbols = ();
16478 foreach my $Interface (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016479 $NameSpaceSymbols{select_Symbol_NS($Interface, 1)}{$Interface} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016480 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016481 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016482 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016483 $REMOVED_INTERFACES .= getTitle($HeaderName, $DyLib, $NameSpace);
16484 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NameSpaceSymbols{$NameSpace}});
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016485 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016486 {
16487 $Removed_Number += 1;
16488 my $SubReport = "";
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016489 my $Signature = get_Signature($Symbol, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016490 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016491 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016492 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016493 if($Symbol=~/\A(_Z|\?)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016494 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016495 if($Signature) {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016496 $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 +040016497 }
16498 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016499 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016500 }
16501 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016502 else
16503 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016504 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016505 $REMOVED_INTERFACES .= "<span class=\"iname\">".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016506 }
16507 else {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016508 $REMOVED_INTERFACES .= "<span class=\"iname\">".$Symbol."</span><br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016509 }
16510 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016511 }
16512 }
16513 $REMOVED_INTERFACES .= "<br/>\n";
16514 }
16515 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016516 if($REMOVED_INTERFACES)
16517 {
16518 my $Anchor = "<a name='Removed'></a><a name='Withdrawn'></a>";
16519 if($JoinReport) {
16520 $Anchor = "<a name='".$Level."_Removed'></a><a name='".$Level."_Withdrawn'></a>";
16521 }
16522 $REMOVED_INTERFACES = $Anchor."<h2>Removed Symbols ($Removed_Number)</h2><hr/>\n".$REMOVED_INTERFACES.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016523 }
16524 }
16525 return $REMOVED_INTERFACES;
16526}
16527
16528sub getXmlParams($$)
16529{
16530 my ($Content, $Problem) = @_;
16531 return "" if(not $Content or not $Problem);
16532 my %XMLparams = ();
16533 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16534 {
16535 my $Macro = "\@".lc($Attr);
16536 if($Content=~/\Q$Macro\E/) {
16537 $XMLparams{lc($Attr)} = $Problem->{$Attr};
16538 }
16539 }
16540 my @PString = ();
16541 foreach my $P (sort {$b cmp $a} keys(%XMLparams)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016542 push(@PString, $P."=\"".xmlSpecChars($XMLparams{$P})."\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016543 }
16544 if(@PString) {
16545 return " ".join(" ", @PString);
16546 }
16547 else {
16548 return "";
16549 }
16550}
16551
16552sub addMarkup($)
16553{
16554 my $Content = $_[0];
16555 # auto-markup
16556 $Content=~s/\n[ ]*//; # spaces
16557 $Content=~s!(\@\w+\s*\(\@\w+\))!<nowrap>$1</nowrap>!g; # @old_type (@old_size)
16558 $Content=~s!(... \(\w+\))!<nowrap><b>$1</b></nowrap>!g; # ... (va_list)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016559 $Content=~s!<nowrap>(.+?)</nowrap>!<span class='nowrap'>$1</span>!g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016560 $Content=~s!([2-9]\))!<br/>$1!g; # 1), 2), ...
16561 if($Content=~/\ANOTE:/)
16562 { # notes
16563 $Content=~s!(NOTE):!<b>$1</b>:!g;
16564 }
16565 else {
16566 $Content=~s!(NOTE):!<br/><b>$1</b>:!g;
16567 }
16568 $Content=~s! (out)-! <b>$1</b>-!g; # out-parameters
16569 my @Keywords = (
16570 "void",
16571 "const",
16572 "static",
16573 "restrict",
16574 "volatile",
16575 "register",
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016576 "virtual"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016577 );
16578 my $MKeys = join("|", @Keywords);
16579 foreach (@Keywords) {
16580 $MKeys .= "|non-".$_;
16581 }
16582 $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 +040016583
16584 # Markdown
16585 $Content=~s!\*\*([\w\-]+)\*\*!<b>$1</b>!ig;
16586 $Content=~s!\*([\w\-]+)\*!<i>$1</i>!ig;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016587 return $Content;
16588}
16589
16590sub applyMacroses($$$$)
16591{
16592 my ($Level, $Kind, $Content, $Problem) = @_;
16593 return "" if(not $Content or not $Problem);
16594 $Problem->{"Word_Size"} = $WORD_SIZE{2};
16595 $Content = addMarkup($Content);
16596 # macros
16597 foreach my $Attr (sort {$b cmp $a} keys(%{$Problem}))
16598 {
16599 my $Macro = "\@".lc($Attr);
16600 my $Value = $Problem->{$Attr};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016601 if(not defined $Value
16602 or $Value eq "") {
16603 next;
16604 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016605 if($Value=~/\s\(/ and $Value!~/['"]/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016606 { # functions
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016607 $Value=~s/\s*\[[\w\-]+\]//g; # remove quals
16608 $Value=~s/\s\w+(\)|,)/$1/g; # remove parameter names
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016609 $Value = black_name($Value);
16610 }
16611 elsif($Value=~/\s/) {
16612 $Value = "<span class='value'>".htmlSpecChars($Value)."</span>";
16613 }
16614 elsif($Value=~/\A\d+\Z/
16615 and ($Attr eq "Old_Size" or $Attr eq "New_Size"))
16616 { # bits to bytes
16617 if($Value % $BYTE_SIZE)
16618 { # bits
16619 if($Value==1) {
16620 $Value = "<b>".$Value."</b> bit";
16621 }
16622 else {
16623 $Value = "<b>".$Value."</b> bits";
16624 }
16625 }
16626 else
16627 { # bytes
16628 $Value /= $BYTE_SIZE;
16629 if($Value==1) {
16630 $Value = "<b>".$Value."</b> byte";
16631 }
16632 else {
16633 $Value = "<b>".$Value."</b> bytes";
16634 }
16635 }
16636 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016637 else
16638 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016639 $Value = "<b>".htmlSpecChars($Value)."</b>";
16640 }
16641 $Content=~s/\Q$Macro\E/$Value/g;
16642 }
16643
16644 if($Content=~/(\A|[^\@\w])\@\w/)
16645 {
16646 if(not $IncompleteRules{$Level}{$Kind})
16647 { # only one warning
16648 printMsg("WARNING", "incomplete rule \"$Kind\" (\"$Level\")");
16649 $IncompleteRules{$Level}{$Kind} = 1;
16650 }
16651 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016652 return $Content;
16653}
16654
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016655sub get_Report_SymbolProblems($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016656{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016657 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016658 my $INTERFACE_PROBLEMS = "";
16659 my (%ReportMap, %SymbolChanges) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016660 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016661 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016662 my ($SN, $SS, $SV) = separate_symbol($Symbol);
16663 if($SV and defined $CompatProblems{$Level}{$SN}) {
16664 next;
16665 }
16666 foreach my $Kind (sort keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016667 {
16668 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Symbols"
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016669 and $Kind ne "Added_Symbol" and $Kind ne "Removed_Symbol")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016670 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016671 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
16672 my $DyLib = $Symbol_Library{1}{$Symbol};
16673 if(not $DyLib and my $VSym = $SymVer{1}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016674 { # Symbol with Version
16675 $DyLib = $Symbol_Library{1}{$VSym};
16676 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016677 if(not $DyLib)
16678 { # const global data
16679 $DyLib = "";
16680 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016681 if($Level eq "Source" and $ReportFormat eq "html")
16682 { # do not show library name in HTML report
16683 $DyLib = "";
16684 }
16685 %{$SymbolChanges{$Symbol}{$Kind}} = %{$CompatProblems{$Level}{$Symbol}{$Kind}};
16686 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016687 {
16688 my $Priority = getProblemSeverity($Level, $Kind);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016689 if($Priority ne $TargetSeverity) {
16690 delete($SymbolChanges{$Symbol}{$Kind}{$Location});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016691 }
16692 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016693 if(not keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16694 {
16695 delete($SymbolChanges{$Symbol}{$Kind});
16696 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016697 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016698 $ReportMap{$HeaderName}{$DyLib}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016699 }
16700 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016701 if(not keys(%{$SymbolChanges{$Symbol}})) {
16702 delete($SymbolChanges{$Symbol});
16703 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016704 }
16705 if($ReportFormat eq "xml")
16706 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016707 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016708 {
16709 $INTERFACE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016710 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016711 {
16712 $INTERFACE_PROBLEMS .= " <library name=\"$DyLib\">\n";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016713 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 +040016714 {
16715 $INTERFACE_PROBLEMS .= " <symbol name=\"$Symbol\">\n";
16716 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
16717 {
16718 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
16719 {
16720 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016721 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016722 $INTERFACE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16723 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16724 $INTERFACE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16725 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16726 $INTERFACE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
16727 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
16728 $INTERFACE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16729 $INTERFACE_PROBLEMS .= " </problem>\n";
16730 }
16731 }
16732 $INTERFACE_PROBLEMS .= " </symbol>\n";
16733 }
16734 $INTERFACE_PROBLEMS .= " </library>\n";
16735 }
16736 $INTERFACE_PROBLEMS .= " </header>\n";
16737 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016738 $INTERFACE_PROBLEMS = "<problems_with_symbols severity=\"$TargetSeverity\">\n".$INTERFACE_PROBLEMS."</problems_with_symbols>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016739 }
16740 else
16741 { # HTML
16742 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016743 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016744 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016745 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016746 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016747 my (%NameSpaceSymbols, %NewSignature) = ();
16748 foreach my $Symbol (keys(%{$ReportMap{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016749 $NameSpaceSymbols{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016750 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016751 foreach my $NameSpace (sort keys(%NameSpaceSymbols))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016752 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016753 $INTERFACE_PROBLEMS .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040016754 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 +040016755 foreach my $Symbol (@SortedInterfaces)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016756 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016757 my $Signature = get_Signature($Symbol, 1);
16758 my $SYMBOL_REPORT = "";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016759 my $ProblemNum = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016760 foreach my $Kind (keys(%{$SymbolChanges{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016761 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016762 foreach my $Location (sort keys(%{$SymbolChanges{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016763 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016764 my %Problem = %{$SymbolChanges{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016765 $Problem{"Param_Pos"} = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016766 if($Problem{"New_Signature"}) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016767 $NewSignature{$Symbol} = $Problem{"New_Signature"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016768 }
16769 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16770 {
16771 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016772 $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 +040016773 $ProblemNum += 1;
16774 $ProblemsNum += 1;
16775 }
16776 }
16777 }
16778 $ProblemNum -= 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016779 if($SYMBOL_REPORT)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016780 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016781 $INTERFACE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016782 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016783 $INTERFACE_PROBLEMS .= highLight_Signature_Italic_Color($Signature);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016784 }
16785 else {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016786 $INTERFACE_PROBLEMS .= $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016787 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016788 $INTERFACE_PROBLEMS .= " ($ProblemNum)".$ContentSpanEnd."<br/>\n";
16789 $INTERFACE_PROBLEMS .= $ContentDivStart."\n";
16790 if($NewSignature{$Symbol})
16791 { # argument list changed to
16792 $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 +040016793 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016794 if($Symbol=~/\A(_Z|\?)/) {
16795 $INTERFACE_PROBLEMS .= "<span class='mangled'>&#160;&#160;&#160;&#160;[symbol: <b>$Symbol</b>]</span><br/>\n";
16796 }
16797 $INTERFACE_PROBLEMS .= "<table class='ptable'><tr><th width='2%'></th><th width='47%'>Change</th><th>Effect</th></tr>$SYMBOL_REPORT</table><br/>\n";
16798 $INTERFACE_PROBLEMS .= $ContentDivEnd;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016799 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016800 $INTERFACE_PROBLEMS=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016801 }
16802 }
16803 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016804 $INTERFACE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016805 }
16806 }
16807 }
16808 if($INTERFACE_PROBLEMS)
16809 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016810 $INTERFACE_PROBLEMS = insertIDs($INTERFACE_PROBLEMS);
16811 my $Title = "Problems with Symbols, $TargetSeverity Severity";
16812 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016813 { # Safe Changes
16814 $Title = "Other Changes in Symbols";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016815 }
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040016816 $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 +040016817 }
16818 }
16819 return $INTERFACE_PROBLEMS;
16820}
16821
16822sub get_Report_TypeProblems($$)
16823{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016824 my ($TargetSeverity, $Level) = @_;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040016825 my $TYPE_PROBLEMS = "";
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016826 my (%ReportMap, %TypeChanges) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016827 foreach my $Interface (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016828 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016829 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Interface}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016830 {
16831 if($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
16832 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016833 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$CompatProblems{$Level}{$Interface}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016834 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016835 my $TypeName = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016836 my $Target = $CompatProblems{$Level}{$Interface}{$Kind}{$Location}{"Target"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016837 my $Severity = getProblemSeverity($Level, $Kind);
16838 if($Severity eq "Safe"
16839 and $TargetSeverity ne "Safe") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016840 next;
16841 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016842
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040016843 if(cmpSeverities($Type_MaxSeverity{$Level}{$TypeName}{$Kind}{$Target}, $Severity))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016844 { # select a problem with the highest priority
16845 next;
16846 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016847 %{$TypeChanges{$TypeName}{$Kind}{$Location}} = %{$CompatProblems{$Level}{$Interface}{$Kind}{$Location}};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016848 }
16849 }
16850 }
16851 }
16852 my %Kinds_Locations = ();
16853 foreach my $TypeName (keys(%TypeChanges))
16854 {
16855 my %Kinds_Target = ();
16856 foreach my $Kind (sort keys(%{$TypeChanges{$TypeName}}))
16857 {
16858 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
16859 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016860 my $Severity = getProblemSeverity($Level, $Kind);
16861 if($Severity ne $TargetSeverity)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016862 { # other priority
16863 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16864 next;
16865 }
16866 $Kinds_Locations{$TypeName}{$Kind}{$Location} = 1;
16867 my $Target = $TypeChanges{$TypeName}{$Kind}{$Location}{"Target"};
16868 if($Kinds_Target{$Kind}{$Target})
16869 { # duplicate target
16870 delete($TypeChanges{$TypeName}{$Kind}{$Location});
16871 next;
16872 }
16873 $Kinds_Target{$Kind}{$Target} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016874 my $HeaderName = $TypeInfo{1}{$TName_Tid{1}{$TypeName}}{"Header"};
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016875 $ReportMap{$HeaderName}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016876 }
16877 if(not keys(%{$TypeChanges{$TypeName}{$Kind}})) {
16878 delete($TypeChanges{$TypeName}{$Kind});
16879 }
16880 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016881 if(not keys(%{$TypeChanges{$TypeName}})) {
16882 delete($TypeChanges{$TypeName});
16883 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016884 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016885 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 +040016886 if($ReportFormat eq "xml")
16887 { # XML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016888 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016889 {
16890 $TYPE_PROBLEMS .= " <header name=\"$HeaderName\">\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016891 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016892 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040016893 $TYPE_PROBLEMS .= " <type name=\"".xmlSpecChars($TypeName)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016894 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16895 {
16896 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
16897 {
16898 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16899 $TYPE_PROBLEMS .= " <problem id=\"$Kind\">\n";
16900 my $Change = $CompatRules{$Level}{$Kind}{"Change"};
16901 $TYPE_PROBLEMS .= " <change".getXmlParams($Change, \%Problem).">$Change</change>\n";
16902 my $Effect = $CompatRules{$Level}{$Kind}{"Effect"};
16903 $TYPE_PROBLEMS .= " <effect".getXmlParams($Effect, \%Problem).">$Effect</effect>\n";
16904 my $Overcome = $CompatRules{$Level}{$Kind}{"Overcome"};
16905 $TYPE_PROBLEMS .= " <overcome".getXmlParams($Overcome, \%Problem).">$Overcome</overcome>\n";
16906 $TYPE_PROBLEMS .= " </problem>\n";
16907 }
16908 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016909 $TYPE_PROBLEMS .= getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016910 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016911 $TYPE_PROBLEMS .= showVTables($TypeName);
16912 }
16913 $TYPE_PROBLEMS .= " </type>\n";
16914 }
16915 $TYPE_PROBLEMS .= " </header>\n";
16916 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016917 $TYPE_PROBLEMS = "<problems_with_types severity=\"$TargetSeverity\">\n".$TYPE_PROBLEMS."</problems_with_types>\n\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016918 }
16919 else
16920 { # HTML
16921 my $ProblemsNum = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016922 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%ReportMap))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016923 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016924 my (%NameSpace_Type) = ();
16925 foreach my $TypeName (keys(%{$ReportMap{$HeaderName}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016926 $NameSpace_Type{select_Type_NS($TypeName, 1)}{$TypeName} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016927 }
16928 foreach my $NameSpace (sort keys(%NameSpace_Type))
16929 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016930 $TYPE_PROBLEMS .= getTitle($HeaderName, "", $NameSpace);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016931 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 +040016932 foreach my $TypeName (@SortedTypes)
16933 {
16934 my $ProblemNum = 1;
16935 my $TYPE_REPORT = "";
16936 foreach my $Kind (sort {$b=~/Size/ <=> $a=~/Size/} sort keys(%{$TypeChanges{$TypeName}}))
16937 {
16938 foreach my $Location (sort {cmp_locations($b, $a)} sort keys(%{$TypeChanges{$TypeName}{$Kind}}))
16939 {
16940 my %Problem = %{$TypeChanges{$TypeName}{$Kind}{$Location}};
16941 if(my $Change = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Change"}, \%Problem))
16942 {
16943 my $Effect = applyMacroses($Level, $Kind, $CompatRules{$Level}{$Kind}{"Effect"}, \%Problem);
16944 $TYPE_REPORT .= "<tr><th>$ProblemNum</th><td align='left' valign='top'>".$Change."</td><td align='left' valign='top'>$Effect</td></tr>\n";
16945 $ProblemNum += 1;
16946 $ProblemsNum += 1;
16947 }
16948 }
16949 }
16950 $ProblemNum -= 1;
16951 if($TYPE_REPORT)
16952 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040016953 my $Affected = getAffectedSymbols($Level, $TypeName, $Kinds_Locations{$TypeName}, \@Symbols);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016954 my $ShowVTables = "";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016955 if($Level eq "Binary" and grep {$_=~/Virtual|Base_Class/} keys(%{$Kinds_Locations{$TypeName}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016956 $ShowVTables = showVTables($TypeName);
16957 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016958
16959 $TYPE_PROBLEMS .= $ContentSpanStart."<span class='extendable'>[+]</span> ".show_Type($TypeName, 1, 1)." ($ProblemNum)".$ContentSpanEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016960 $TYPE_PROBLEMS .= "<br/>\n".$ContentDivStart."<table class='ptable'><tr>\n";
16961 $TYPE_PROBLEMS .= "<th width='2%'></th><th width='47%'>Change</th>\n";
16962 $TYPE_PROBLEMS .= "<th>Effect</th></tr>".$TYPE_REPORT."</table>\n";
16963 $TYPE_PROBLEMS .= $ShowVTables.$Affected."<br/><br/>".$ContentDivEnd."\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016964 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040016965 $TYPE_PROBLEMS=~s/\b\Q$NameSpace\E::(\w|\~)/$1/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016966 }
16967 }
16968 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016969 $TYPE_PROBLEMS .= "<br/>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016970 }
16971 }
16972 if($TYPE_PROBLEMS)
16973 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016974 $TYPE_PROBLEMS = insertIDs($TYPE_PROBLEMS);
16975 my $Title = "Problems with Data Types, $TargetSeverity Severity";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016976 if($TargetSeverity eq "Safe")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016977 { # Safe Changes
16978 $Title = "Other Changes in Data Types";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040016979 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040016980 $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 +040016981 }
16982 }
16983 return $TYPE_PROBLEMS;
16984}
16985
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040016986sub show_Type($$$)
16987{
16988 my ($Name, $Html, $LibVersion) = @_;
16989 my $TType = $TypeInfo{$LibVersion}{$TName_Tid{$LibVersion}{$Name}}{"Type"};
16990 $TType = lc($TType);
16991 if($TType=~/struct|union|enum/) {
16992 $Name=~s/\A\Q$TType\E //g;
16993 }
16994 if($Html) {
16995 $Name = "<span class='ttype'>".$TType."</span> ".htmlSpecChars($Name);
16996 }
16997 else {
16998 $Name = $TType." ".$Name;
16999 }
17000 return $Name;
17001}
17002
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017003sub get_Anchor($$$)
17004{
17005 my ($Kind, $Level, $Severity) = @_;
17006 if($JoinReport)
17007 {
17008 if($Severity eq "Safe") {
17009 return "Other_".$Level."_Changes_In_".$Kind."s";
17010 }
17011 else {
17012 return $Kind."_".$Level."_Problems_".$Severity;
17013 }
17014 }
17015 else
17016 {
17017 if($Severity eq "Safe") {
17018 return "Other_Changes_In_".$Kind."s";
17019 }
17020 else {
17021 return $Kind."_Problems_".$Severity;
17022 }
17023 }
17024}
17025
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017026sub showVTables($)
17027{
17028 my $TypeName = $_[0];
17029 my $TypeId1 = $TName_Tid{1}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017030 my %Type1 = get_Type($TypeId1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017031 if(defined $Type1{"VTable"}
17032 and keys(%{$Type1{"VTable"}}))
17033 {
17034 my $TypeId2 = $TName_Tid{2}{$TypeName};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017035 my %Type2 = get_Type($TypeId2, 2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017036 if(defined $Type2{"VTable"}
17037 and keys(%{$Type2{"VTable"}}))
17038 {
17039 my %Indexes = map {$_=>1} (keys(%{$Type1{"VTable"}}), keys(%{$Type2{"VTable"}}));
17040 my %Entries = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017041 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Indexes)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017042 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017043 $Entries{$Index}{"E1"} = simpleVEntry($Type1{"VTable"}{$Index});
17044 $Entries{$Index}{"E2"} = simpleVEntry($Type2{"VTable"}{$Index});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017045 }
17046 my $VTABLES = "";
17047 if($ReportFormat eq "xml")
17048 { # XML
17049 $VTABLES .= " <vtable>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017050 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017051 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017052 $VTABLES .= " <entry offset=\"".$Index."\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017053 $VTABLES .= " <old>".xmlSpecChars($Entries{$Index}{"E1"})."</old>\n";
17054 $VTABLES .= " <new>".xmlSpecChars($Entries{$Index}{"E2"})."</new>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017055 $VTABLES .= " </entry>\n";
17056 }
17057 $VTABLES .= " </vtable>\n\n";
17058 }
17059 else
17060 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017061 $VTABLES .= "<table class='vtable'>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017062 $VTABLES .= "<tr><th width='2%'>Offset</th>";
17063 $VTABLES .= "<th width='45%'>Virtual Table (Old) - ".(keys(%{$Type1{"VTable"}}))." entries</th>";
17064 $VTABLES .= "<th>Virtual Table (New) - ".(keys(%{$Type2{"VTable"}}))." entries</th></tr>";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017065 foreach my $Index (sort {int($a)<=>int($b)} (keys(%Entries)))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017066 {
17067 my ($Color1, $Color2) = ("", "");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017068 if($Entries{$Index}{"E1"} ne $Entries{$Index}{"E2"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017069 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017070 if($Entries{$Index}{"E1"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017071 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017072 $Color1 = " class='failed'";
17073 $Color2 = " class='failed'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017074 }
17075 else {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017076 $Color2 = " class='warning'";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017077 }
17078 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017079 $VTABLES .= "<tr><th>".$Index."</th>\n";
17080 $VTABLES .= "<td$Color1>".htmlSpecChars($Entries{$Index}{"E1"})."</td>\n";
17081 $VTABLES .= "<td$Color2>".htmlSpecChars($Entries{$Index}{"E2"})."</td></tr>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017082 }
17083 $VTABLES .= "</table><br/>\n";
17084 $VTABLES = $ContentDivStart.$VTABLES.$ContentDivEnd;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017085 $VTABLES = $ContentSpanStart_Info."[+] show v-table (old and new)".$ContentSpanEnd."<br/>\n".$VTABLES;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017086 }
17087 return $VTABLES;
17088 }
17089 }
17090 return "";
17091}
17092
17093sub simpleVEntry($)
17094{
17095 my $VEntry = $_[0];
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017096 if(not defined $VEntry
17097 or $VEntry eq "") {
17098 return "";
17099 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017100 $VEntry=~s/\A(.+)::(_ZThn.+)\Z/$2/; # thunks
17101 $VEntry=~s/_ZTI\w+/typeinfo/g; # typeinfo
17102 if($VEntry=~/\A_ZThn.+\Z/) {
17103 $VEntry = "non-virtual thunk";
17104 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017105 $VEntry=~s/\A\(int \(\*\)\(...\)\)\s*([a-z_])/$1/i;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017106 # support for old GCC versions
17107 $VEntry=~s/\A0u\Z/(int (*)(...))0/;
17108 $VEntry=~s/\A4294967268u\Z/(int (*)(...))-0x000000004/;
17109 $VEntry=~s/\A&_Z\Z/& _Z/;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017110 $VEntry=~s/([^:]+)::\~([^:]+)\Z/~$1/; # destructors
17111 return $VEntry;
17112}
17113
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017114sub getAffectedSymbols($$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017115{
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017116 my ($Level, $Target_TypeName, $Kinds_Locations, $Syms) = @_;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017117 my $LIMIT = 1000;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017118 if($#{$Syms}>=10000)
17119 { # reduce size of the report
17120 $LIMIT = 10;
17121 }
17122 my %SProblems = ();
17123 foreach my $Symbol (@{$Syms})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017124 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017125 if(keys(%SProblems)>$LIMIT) {
17126 last;
17127 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017128 if(($Symbol=~/C2E|D2E|D0E/))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017129 { # duplicated problems for C2 constructors, D2 and D0 destructors
17130 next;
17131 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017132 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17133 if($Level eq "Source")
17134 { # remove symbol version
17135 $Symbol=$SN;
17136 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017137 my ($MinPath_Length, $ProblemLocation_Last) = (-1, "");
17138 my $Severity_Max = 0;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017139 my $Signature = get_Signature($Symbol, 1);
17140 foreach my $Kind (keys(%{$CompatProblems{$Level}{$Symbol}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017141 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017142 foreach my $Location (keys(%{$CompatProblems{$Level}{$Symbol}{$Kind}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017143 {
17144 if(not defined $Kinds_Locations->{$Kind}
17145 or not $Kinds_Locations->{$Kind}{$Location}) {
17146 next;
17147 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017148 if($SV and defined $CompatProblems{$Level}{$SN}
17149 and defined $CompatProblems{$Level}{$SN}{$Kind}{$Location})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017150 { # duplicated problems for versioned symbols
17151 next;
17152 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017153 my $Type_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Type_Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017154 next if($Type_Name ne $Target_TypeName);
17155
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017156 my $Position = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Param_Pos"};
17157 my $Param_Name = $CompatProblems{$Level}{$Symbol}{$Kind}{$Location}{"Param_Name"};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017158 my $Severity = getProblemSeverity($Level, $Kind);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017159 my $Path_Length = 0;
17160 my $ProblemLocation = $Location;
17161 if($Type_Name) {
17162 $ProblemLocation=~s/->\Q$Type_Name\E\Z//g;
17163 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017164 while($ProblemLocation=~/\-\>/g) {
17165 $Path_Length += 1;
17166 }
17167 if($MinPath_Length==-1 or ($Path_Length<=$MinPath_Length and $Severity_Val{$Severity}>$Severity_Max)
17168 or (cmp_locations($ProblemLocation, $ProblemLocation_Last) and $Severity_Val{$Severity}==$Severity_Max))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017169 {
17170 $MinPath_Length = $Path_Length;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017171 $Severity_Max = $Severity_Val{$Severity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017172 $ProblemLocation_Last = $ProblemLocation;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017173 %{$SProblems{$Symbol}} = (
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017174 "Descr"=>getAffectDescription($Level, $Symbol, $Kind, $Location),
17175 "Severity_Max"=>$Severity_Max,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017176 "Signature"=>$Signature,
17177 "Position"=>$Position,
17178 "Param_Name"=>$Param_Name,
17179 "Location"=>$Location
17180 );
17181 }
17182 }
17183 }
17184 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017185 my @Symbols = keys(%SProblems);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017186 @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 +040017187 @Symbols = sort {$SProblems{$b}{"Severity_Max"}<=>$SProblems{$a}{"Severity_Max"}} @Symbols;
17188 if($#Symbols+1>$LIMIT)
17189 { # remove last element
17190 pop(@Symbols);
17191 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017192 my $Affected = "";
17193 if($ReportFormat eq "xml")
17194 { # XML
17195 $Affected .= " <affected>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017196 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017197 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017198 my $Param_Name = $SProblems{$Symbol}{"Param_Name"};
17199 my $Description = $SProblems{$Symbol}{"Descr"};
17200 my $Location = $SProblems{$Symbol}{"Location"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017201 my $Target = "";
17202 if($Param_Name) {
17203 $Target = " affected=\"param\" param_name=\"$Param_Name\"";
17204 }
17205 elsif($Location=~/\Aretval(\-|\Z)/i) {
17206 $Target = " affected=\"retval\"";
17207 }
17208 elsif($Location=~/\Athis(\-|\Z)/i) {
17209 $Target = " affected=\"this\"";
17210 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017211 $Affected .= " <symbol$Target name=\"$Symbol\">\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017212 $Affected .= " <comment>".xmlSpecChars($Description)."</comment>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017213 $Affected .= " </symbol>\n";
17214 }
17215 $Affected .= " </affected>\n";
17216 }
17217 else
17218 { # HTML
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017219 foreach my $Symbol (@Symbols)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017220 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017221 my $Description = $SProblems{$Symbol}{"Descr"};
17222 my $Signature = $SProblems{$Symbol}{"Signature"};
17223 my $Pos = $SProblems{$Symbol}{"Position"};
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017224 $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 +040017225 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017226 if(keys(%SProblems)>$LIMIT) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017227 $Affected .= "and others ...<br/>";
17228 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017229 $Affected = "<div class='affected'>".$Affected."</div>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017230 if($Affected)
17231 {
17232 $Affected = $ContentDivStart.$Affected.$ContentDivEnd;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017233 $Affected = $ContentSpanStart_Affected."[+] affected symbols (".(keys(%SProblems)>$LIMIT?">".$LIMIT:keys(%SProblems)).")".$ContentSpanEnd.$Affected;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017234 }
17235 }
17236 return $Affected;
17237}
17238
17239sub cmp_locations($$)
17240{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017241 my ($L1, $L2) = @_;
17242 if($L2=~/\b(retval|this)\b/
17243 and $L1!~/\b(retval|this)\b/ and $L1!~/\-\>/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017244 return 1;
17245 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017246 if($L2=~/\b(retval|this)\b/ and $L2=~/\-\>/
17247 and $L1!~/\b(retval|this)\b/ and $L1=~/\-\>/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017248 return 1;
17249 }
17250 return 0;
17251}
17252
17253sub getAffectDescription($$$$)
17254{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017255 my ($Level, $Symbol, $Kind, $Location) = @_;
17256 my %Problem = %{$CompatProblems{$Level}{$Symbol}{$Kind}{$Location}};
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017257 my $PPos = showPos($Problem{"Param_Pos"});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017258 my @Sentence = ();
17259 $Location=~s/\A(.*)\-\>.+?\Z/$1/;
17260 if($Kind eq "Overridden_Virtual_Method"
17261 or $Kind eq "Overridden_Virtual_Method_B") {
17262 push(@Sentence, "The method '".$Problem{"New_Value"}."' will be called instead of this method.");
17263 }
17264 elsif($CompatRules{$Level}{$Kind}{"Kind"} eq "Types")
17265 {
17266 if($Location eq "this" or $Kind=~/(\A|_)Virtual(_|\Z)/)
17267 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017268 my $METHOD_TYPE = $CompleteSignature{1}{$Symbol}{"Constructor"}?"constructor":"method";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017269 my $ClassName = $TypeInfo{1}{$CompleteSignature{1}{$Symbol}{"Class"}}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017270 if($ClassName eq $Problem{"Type_Name"}) {
17271 push(@Sentence, "This $METHOD_TYPE is from \'".$Problem{"Type_Name"}."\' class.");
17272 }
17273 else {
17274 push(@Sentence, "This $METHOD_TYPE is from derived class \'".$ClassName."\'.");
17275 }
17276 }
17277 else
17278 {
17279 if($Location=~/retval/)
17280 { # return value
17281 if($Location=~/\-\>/) {
17282 push(@Sentence, "Field \'".$Location."\' in return value");
17283 }
17284 else {
17285 push(@Sentence, "Return value");
17286 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017287 if(my $Init = $Problem{"InitialType_Type"})
17288 {
17289 if($Init eq "Pointer") {
17290 push(@Sentence, "(pointer)");
17291 }
17292 elsif($Init eq "Ref") {
17293 push(@Sentence, "(reference)");
17294 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017295 }
17296 }
17297 elsif($Location=~/this/)
17298 { # "this" pointer
17299 if($Location=~/\-\>/) {
17300 push(@Sentence, "Field \'".$Location."\' in the object of this method");
17301 }
17302 else {
17303 push(@Sentence, "\'this\' pointer");
17304 }
17305 }
17306 else
17307 { # parameters
17308 if($Location=~/\-\>/) {
17309 push(@Sentence, "Field \'".$Location."\' in $PPos parameter");
17310 }
17311 else {
17312 push(@Sentence, "$PPos parameter");
17313 }
17314 if($Problem{"Param_Name"}) {
17315 push(@Sentence, "\'".$Problem{"Param_Name"}."\'");
17316 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017317 if(my $Init = $Problem{"InitialType_Type"})
17318 {
17319 if($Init eq "Pointer") {
17320 push(@Sentence, "(pointer)");
17321 }
17322 elsif($Init eq "Ref") {
17323 push(@Sentence, "(reference)");
17324 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017325 }
17326 }
17327 if($Location eq "this") {
17328 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17329 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017330 elsif(defined $Problem{"Start_Type_Name"}
17331 and $Problem{"Start_Type_Name"} eq $Problem{"Type_Name"}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017332 push(@Sentence, "has type \'".$Problem{"Type_Name"}."\'.");
17333 }
17334 else {
17335 push(@Sentence, "has base type \'".$Problem{"Type_Name"}."\'.");
17336 }
17337 }
17338 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017339 if($ExtendedSymbols{$Symbol}) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017340 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 +040017341 }
17342 return join(" ", @Sentence);
17343}
17344
17345sub get_XmlSign($$)
17346{
17347 my ($Symbol, $LibVersion) = @_;
17348 my $Info = $CompleteSignature{$LibVersion}{$Symbol};
17349 my $Report = "";
17350 foreach my $Pos (sort {int($a)<=>int($b)} keys(%{$Info->{"Param"}}))
17351 {
17352 my $Name = $Info->{"Param"}{$Pos}{"name"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017353 my $Type = $Info->{"Param"}{$Pos}{"type"};
17354 my $TypeName = $TypeInfo{$LibVersion}{$Type}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017355 foreach my $Typedef (keys(%ChangedTypedef))
17356 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017357 if(my $Base = $Typedef_BaseName{$LibVersion}{$Typedef}) {
17358 $TypeName=~s/\b\Q$Typedef\E\b/$Base/g;
17359 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017360 }
17361 $Report .= " <param pos=\"$Pos\">\n";
17362 $Report .= " <name>".$Name."</name>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017363 $Report .= " <type>".xmlSpecChars($TypeName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017364 $Report .= " </param>\n";
17365 }
17366 if(my $Return = $Info->{"Return"})
17367 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017368 my $RTName = $TypeInfo{$LibVersion}{$Return}{"Name"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017369 $Report .= " <retval>\n";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017370 $Report .= " <type>".xmlSpecChars($RTName)."</type>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017371 $Report .= " </retval>\n";
17372 }
17373 return $Report;
17374}
17375
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017376sub get_Report_SymbolsInfo($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017377{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017378 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017379 my $Report = "<symbols_info>\n";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017380 foreach my $Symbol (sort keys(%{$CompatProblems{$Level}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017381 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017382 my ($SN, $SS, $SV) = separate_symbol($Symbol);
17383 if($SV and defined $CompatProblems{$Level}{$SN}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017384 next;
17385 }
17386 $Report .= " <symbol name=\"$Symbol\">\n";
17387 my ($S1, $P1, $S2, $P2) = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017388 if(not $AddedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017389 {
17390 if(defined $CompleteSignature{1}{$Symbol}
17391 and defined $CompleteSignature{1}{$Symbol}{"Header"})
17392 {
17393 $P1 = get_XmlSign($Symbol, 1);
17394 $S1 = get_Signature($Symbol, 1);
17395 }
17396 elsif($Symbol=~/\A(_Z|\?)/) {
17397 $S1 = $tr_name{$Symbol};
17398 }
17399 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017400 if(not $RemovedInt{$Level}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017401 {
17402 if(defined $CompleteSignature{2}{$Symbol}
17403 and defined $CompleteSignature{2}{$Symbol}{"Header"})
17404 {
17405 $P2 = get_XmlSign($Symbol, 2);
17406 $S2 = get_Signature($Symbol, 2);
17407 }
17408 elsif($Symbol=~/\A(_Z|\?)/) {
17409 $S2 = $tr_name{$Symbol};
17410 }
17411 }
17412 if($S1)
17413 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017414 $Report .= " <old signature=\"".xmlSpecChars($S1)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017415 $Report .= $P1;
17416 $Report .= " </old>\n";
17417 }
17418 if($S2 and $S2 ne $S1)
17419 {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040017420 $Report .= " <new signature=\"".xmlSpecChars($S2)."\">\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017421 $Report .= $P2;
17422 $Report .= " </new>\n";
17423 }
17424 $Report .= " </symbol>\n";
17425 }
17426 $Report .= "</symbols_info>\n";
17427 return $Report;
17428}
17429
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017430sub writeReport($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017431{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017432 my ($Level, $Report) = @_;
17433 if($ReportFormat eq "xml") {
17434 $Report = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".$Report;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017435 }
17436 if($StdOut)
17437 { # --stdout option
17438 print STDOUT $Report;
17439 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017440 else
17441 {
17442 my $RPath = getReportPath($Level);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040017443 mkpath(get_dirname($RPath));
17444
17445 open(REPORT, ">", $RPath) || die ("can't open file \'$RPath\': $!\n");
17446 print REPORT $Report;
17447 close(REPORT);
17448
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017449 if($Browse or $OpenReport)
17450 { # open in browser
17451 openReport($RPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017452 if($JoinReport or $DoubleReport)
17453 {
17454 if($Level eq "Binary")
17455 { # wait to open a browser
17456 sleep(1);
17457 }
17458 }
17459 }
17460 }
17461}
17462
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017463sub openReport($)
17464{
17465 my $Path = $_[0];
17466 my $Cmd = "";
17467 if($Browse)
17468 { # user-defined browser
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017469 $Cmd = $Browse." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017470 }
17471 if(not $Cmd)
17472 { # default browser
17473 if($OSgroup eq "macos") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017474 $Cmd = "open \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017475 }
17476 elsif($OSgroup eq "windows") {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017477 $Cmd = "start ".path_format($Path, $OSgroup);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017478 }
17479 else
17480 { # linux, freebsd, solaris
17481 my @Browsers = (
17482 "x-www-browser",
17483 "sensible-browser",
17484 "firefox",
17485 "opera",
17486 "xdg-open",
17487 "lynx",
17488 "links"
17489 );
17490 foreach my $Br (@Browsers)
17491 {
17492 if($Br = get_CmdPath($Br))
17493 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017494 $Cmd = $Br." \"$Path\"";
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017495 last;
17496 }
17497 }
17498 }
17499 }
17500 if($Cmd)
17501 {
17502 if($Debug) {
17503 printMsg("INFO", "running $Cmd");
17504 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017505 if($OSgroup ne "windows"
17506 and $OSgroup ne "macos")
17507 {
17508 if($Cmd!~/lynx|links/) {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017509 $Cmd .= " >\"/dev/null\" 2>&1 &";
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040017510 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040017511 }
17512 system($Cmd);
17513 }
17514 else {
17515 printMsg("ERROR", "cannot open report in browser");
17516 }
17517}
17518
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017519sub getReport($)
17520{
17521 my $Level = $_[0];
17522 if($ReportFormat eq "xml")
17523 { # XML
17524
17525 if($Level eq "Join")
17526 {
17527 my $Report = "<reports>\n";
17528 $Report .= getReport("Binary");
17529 $Report .= getReport("Source");
17530 $Report .= "</reports>\n";
17531 return $Report;
17532 }
17533 else
17534 {
17535 my $Report = "<report kind=\"".lc($Level)."\" version=\"$XML_REPORT_VERSION\">\n\n";
17536 my ($Summary, $MetaData) = get_Summary($Level);
17537 $Report .= $Summary."\n";
17538 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17539 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17540 $Report .= get_Report_SymbolsInfo($Level);
17541 $Report .= "</report>\n";
17542 return $Report;
17543 }
17544 }
17545 else
17546 { # HTML
17547 my $CssStyles = readModule("Styles", "Report.css");
17548 my $JScripts = readModule("Scripts", "Sections.js");
17549 if($Level eq "Join")
17550 {
17551 $CssStyles .= "\n".readModule("Styles", "Tabs.css");
17552 $JScripts .= "\n".readModule("Scripts", "Tabs.js");
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040017553 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." compatibility report";
17554 my $Keywords = $TargetLibraryFName.", compatibility, API, report";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017555 my $Description = "Compatibility report for the $TargetLibraryFName $TargetComponent between ".$Descriptor{1}{"Version"}." and ".$Descriptor{2}{"Version"}." versions";
17556 my ($BSummary, $BMetaData) = get_Summary("Binary");
17557 my ($SSummary, $SMetaData) = get_Summary("Source");
17558 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>";
17559 $Report .= get_Report_Header("Join")."
17560 <br/><div class='tabset'>
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017561 <a id='BinaryID' href='#BinaryTab' class='tab active'>Binary<br/>Compatibility</a>
17562 <a id='SourceID' href='#SourceTab' style='margin-left:3px' class='tab disabled'>Source<br/>Compatibility</a>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017563 </div>";
17564 $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>";
17565 $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 +040017566 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017567 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
17568 return $Report;
17569 }
17570 else
17571 {
17572 my ($Summary, $MetaData) = get_Summary($Level);
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040017573 my $Title = $TargetLibraryFName.": ".$Descriptor{1}{"Version"}." to ".$Descriptor{2}{"Version"}." ".lc($Level)." compatibility report";
17574 my $Keywords = $TargetLibraryFName.", ".lc($Level)." compatibility, API, report";
17575 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 +040017576 if($Level eq "Binary")
17577 {
17578 if(getArch(1) eq getArch(2)
17579 and getArch(1) ne "unknown") {
17580 $Description .= " on ".showArch(getArch(1));
17581 }
17582 }
17583 my $Report = "<!-\- $MetaData -\->\n".composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."\n<body>\n<div><a name='Top'></a>\n";
17584 $Report .= get_Report_Header($Level)."\n".$Summary."\n";
17585 $Report .= get_Report_Added($Level).get_Report_Removed($Level);
17586 $Report .= get_Report_Problems("High", $Level).get_Report_Problems("Medium", $Level).get_Report_Problems("Low", $Level).get_Report_Problems("Safe", $Level);
17587 $Report .= get_SourceInfo();
17588 $Report .= "</div>\n<br/><br/><br/><hr/>\n";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017589 $Report .= getReportFooter($TargetLibraryFName, not $JoinReport);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017590 $Report .= "\n<div style='height:999px;'></div>\n</body></html>";
17591 return $Report;
17592 }
17593 }
17594}
17595
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017596sub getLegend()
17597{
17598 return "<br/>
17599<table class='summary'>
17600<tr>
17601 <td class='new'>added</td>
17602 <td class='passed'>compatible</td>
17603</tr>
17604<tr>
17605 <td class='warning'>warning</td>
17606 <td class='failed'>incompatible</td>
17607</tr></table>\n";
17608}
17609
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017610sub createReport()
17611{
17612 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040017613 { # --stdout
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017614 writeReport("Join", getReport("Join"));
17615 }
17616 elsif($DoubleReport)
17617 { # default
17618 writeReport("Binary", getReport("Binary"));
17619 writeReport("Source", getReport("Source"));
17620 }
17621 elsif($BinaryOnly)
17622 { # --binary
17623 writeReport("Binary", getReport("Binary"));
17624 }
17625 elsif($SourceOnly)
17626 { # --source
17627 writeReport("Source", getReport("Source"));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017628 }
17629}
17630
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017631sub getReportFooter($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017632{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017633 my ($LibName, $Wide) = @_;
17634 my $FooterStyle = $Wide?"width:99%":"width:97%;padding-top:3px";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017635 my $Footer = "<div style='$FooterStyle;font-size:11px;' align='right'><i>Generated on ".(localtime time); # report date
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017636 $Footer .= " for <span style='font-weight:bold'>$LibName</span>"; # tested library/system name
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017637 $Footer .= " by <a href='".$HomePage{"Wiki"}."'>ABI Compliance Checker</a>"; # tool name
17638 my $ToolSummary = "<br/>A tool for checking backward compatibility of a C/C++ library API&#160;&#160;";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017639 $Footer .= " $TOOL_VERSION &#160;$ToolSummary</i></div>"; # tool version
17640 return $Footer;
17641}
17642
17643sub get_Report_Problems($$)
17644{
17645 my ($Priority, $Level) = @_;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017646 my $Report = get_Report_TypeProblems($Priority, $Level);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017647 if(my $SProblems = get_Report_SymbolProblems($Priority, $Level)) {
17648 $Report .= $SProblems;
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040017649 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017650 if($Priority eq "Low")
17651 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017652 $Report .= get_Report_ChangedConstants("Low", $Level);
Andrey Ponomarenko82bc2572012-11-14 13:55:30 +040017653 if($ReportFormat eq "html")
17654 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017655 if($CheckImpl and $Level eq "Binary") {
17656 $Report .= get_Report_Impl();
17657 }
17658 }
17659 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017660 if($Priority eq "Safe")
17661 {
17662 $Report .= get_Report_ChangedConstants("Safe", $Level);
17663 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017664 if($ReportFormat eq "html")
17665 {
17666 if($Report)
17667 { # add anchor
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017668 if($JoinReport)
17669 {
17670 if($Priority eq "Safe") {
17671 $Report = "<a name=\'Other_".$Level."_Changes\'></a>".$Report;
17672 }
17673 else {
17674 $Report = "<a name=\'".$Priority."_Risk_".$Level."_Problems\'></a>".$Report;
17675 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017676 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017677 else
17678 {
17679 if($Priority eq "Safe") {
17680 $Report = "<a name=\'Other_Changes\'></a>".$Report;
17681 }
17682 else {
17683 $Report = "<a name=\'".$Priority."_Risk_Problems\'></a>".$Report;
17684 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017685 }
17686 }
17687 }
17688 return $Report;
17689}
17690
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017691sub composeHTML_Head($$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017692{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017693 my ($Title, $Keywords, $Description, $Styles, $Scripts) = @_;
17694 return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
17695 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
17696 <head>
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017697 <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
17698 <meta name=\"keywords\" content=\"$Keywords\" />
17699 <meta name=\"description\" content=\"$Description\" />
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017700 <title>
17701 $Title
17702 </title>
17703 <style type=\"text/css\">
17704 $Styles
17705 </style>
17706 <script type=\"text/javascript\" language=\"JavaScript\">
17707 <!--
17708 $Scripts
17709 -->
17710 </script>
17711 </head>";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017712}
17713
17714sub insertIDs($)
17715{
17716 my $Text = $_[0];
17717 while($Text=~/CONTENT_ID/)
17718 {
17719 if(int($Content_Counter)%2) {
17720 $ContentID -= 1;
17721 }
17722 $Text=~s/CONTENT_ID/c_$ContentID/;
17723 $ContentID += 1;
17724 $Content_Counter += 1;
17725 }
17726 return $Text;
17727}
17728
17729sub checkPreprocessedUnit($)
17730{
17731 my $Path = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017732 my ($CurHeader, $CurHeaderName) = ("", "");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017733 my $CurClass = ""; # extra info
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017734 open(PREPROC, $Path) || die ("can't open file \'$Path\': $!\n");
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017735
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017736 while(my $Line = <PREPROC>)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040017737 { # detecting public and private constants
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017738 if(substr($Line, 0, 1) eq "#")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017739 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017740 chomp($Line);
17741 if($Line=~/\A\#\s+\d+\s+\"(.+)\"/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017742 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017743 $CurHeader = path_format($1, $OSgroup);
17744 $CurHeaderName = get_filename($CurHeader);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017745 $CurClass = "";
17746
17747 if(index($CurHeader, $TMP_DIR)==0) {
17748 next;
17749 }
17750
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017751 if(substr($CurHeaderName, 0, 1) eq "<")
17752 { # <built-in>, <command-line>, etc.
17753 $CurHeaderName = "";
17754 $CurHeader = "";
17755 }
17756
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017757 if($ExtraInfo)
17758 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017759 if($CurHeaderName) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017760 $PreprocessedHeaders{$Version}{$CurHeader} = 1;
17761 }
17762 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017763 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017764 if(not $ExtraDump)
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017765 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017766 if($CurHeaderName)
17767 {
17768 if(not $Include_Neighbors{$Version}{$CurHeaderName}
17769 and not $Registered_Headers{$Version}{$CurHeader})
17770 { # not a target
17771 next;
17772 }
17773 if(not is_target_header($CurHeaderName, 1)
17774 and not is_target_header($CurHeaderName, 2))
17775 { # user-defined header
17776 next;
17777 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017778 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017779 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040017780
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017781 if($Line=~/\A\#\s*define\s+(\w+)\s+(.+)\s*\Z/)
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017782 {
17783 my ($Name, $Value) = ($1, $2);
17784 if(not $Constants{$Version}{$Name}{"Access"})
17785 {
17786 $Constants{$Version}{$Name}{"Access"} = "public";
17787 $Constants{$Version}{$Name}{"Value"} = $Value;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017788 if($CurHeaderName) {
17789 $Constants{$Version}{$Name}{"Header"} = $CurHeaderName;
17790 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017791 }
17792 }
17793 elsif($Line=~/\A\#[ \t]*undef[ \t]+([_A-Z]+)[ \t]*/) {
17794 $Constants{$Version}{$1}{"Access"} = "private";
17795 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017796 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017797 else
17798 {
17799 if(defined $ExtraDump)
17800 {
17801 if($Line=~/(\w+)\s*\(/)
17802 { # functions
17803 $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17804 }
17805 #elsif($Line=~/(\w+)\s*;/)
17806 #{ # data
17807 # $SymbolHeader{$Version}{$CurClass}{$1} = $CurHeader;
17808 #}
17809 elsif($Line=~/(\A|\s)class\s+(\w+)/) {
17810 $CurClass = $2;
17811 }
17812 }
17813 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017814 }
17815 close(PREPROC);
17816 foreach my $Constant (keys(%{$Constants{$Version}}))
17817 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017818 if($Constants{$Version}{$Constant}{"Access"} eq "private")
17819 {
17820 delete($Constants{$Version}{$Constant});
17821 next;
17822 }
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040017823 if(not $ExtraDump and ($Constant=~/_h\Z/i
17824 or isBuiltIn($Constants{$Version}{$Constant}{"Header"})))
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040017825 { # skip
17826 delete($Constants{$Version}{$Constant});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017827 }
17828 else {
17829 delete($Constants{$Version}{$Constant}{"Access"});
17830 }
17831 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040017832 if($Debug)
17833 {
17834 mkpath($DEBUG_PATH{$Version});
17835 copy($Path, $DEBUG_PATH{$Version}."/preprocessor.txt");
17836 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017837}
17838
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017839sub uncoverConstant($$)
17840{
17841 my ($LibVersion, $Constant) = @_;
17842 return "" if(not $LibVersion or not $Constant);
17843 return $Constant if(isCyclical(\@RecurConstant, $Constant));
17844 if(defined $Cache{"uncoverConstant"}{$LibVersion}{$Constant}) {
17845 return $Cache{"uncoverConstant"}{$LibVersion}{$Constant};
17846 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017847
17848 if(defined $Constants{$LibVersion}{$Constant})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017849 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017850 my $Value = $Constants{$LibVersion}{$Constant}{"Value"};
17851 if(defined $Constants{$LibVersion}{$Value})
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017852 {
17853 push(@RecurConstant, $Constant);
17854 my $Uncovered = uncoverConstant($LibVersion, $Value);
17855 if($Uncovered ne "") {
17856 $Value = $Uncovered;
17857 }
17858 pop(@RecurConstant);
17859 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017860
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017861 # FIXME: uncover $Value using all the enum constants
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017862 # USE CASE: change of define NC_LONG from NC_INT (enum value) to NC_INT (define)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040017863 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = $Value);
17864 }
17865 return ($Cache{"uncoverConstant"}{$LibVersion}{$Constant} = "");
17866}
17867
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017868sub simpleConstant($$)
17869{
17870 my ($LibVersion, $Value) = @_;
17871 if($Value=~/\W/)
17872 {
17873 my $Value_Copy = $Value;
17874 while($Value_Copy=~s/([a-z_]\w+)/\@/i)
17875 {
17876 my $Word = $1;
17877 if($Value!~/$Word\s*\(/)
17878 {
17879 my $Val = uncoverConstant($LibVersion, $Word);
17880 if($Val ne "")
17881 {
17882 $Value=~s/\b$Word\b/$Val/g;
17883 }
17884 }
17885 }
17886 }
17887 return $Value;
17888}
17889
17890sub computeValue($)
17891{
17892 my $Value = $_[0];
17893
17894 if($Value=~/\A\((-?[\d]+)\)\Z/) {
17895 return $1;
17896 }
17897
17898 if($Value=~/\A[\d\-\+()]+\Z/) {
17899 return eval($Value);
17900 }
17901
17902 return $Value;
17903}
17904
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040017905my %IgnoreConstant = map {$_=>1} (
17906 "VERSION",
17907 "VERSIONCODE",
17908 "VERNUM",
17909 "VERS_INFO",
17910 "PATCHLEVEL",
17911 "INSTALLPREFIX",
17912 "VBUILD",
17913 "VPATCH",
17914 "VMINOR",
17915 "BUILD_STRING",
17916 "BUILD_TIME",
17917 "PACKAGE_STRING",
17918 "PRODUCTION",
17919 "CONFIGURE_COMMAND",
17920 "INSTALLDIR",
17921 "BINDIR",
17922 "CONFIG_FILE_PATH",
17923 "DATADIR",
17924 "EXTENSION_DIR",
17925 "INCLUDE_PATH",
17926 "LIBDIR",
17927 "LOCALSTATEDIR",
17928 "SBINDIR",
17929 "SYSCONFDIR",
17930 "RELEASE",
17931 "SOURCE_ID",
17932 "SUBMINOR",
17933 "MINOR",
17934 "MINNOR",
17935 "MINORVERSION",
17936 "MAJOR",
17937 "MAJORVERSION",
17938 "MICRO",
17939 "MICROVERSION",
17940 "BINARY_AGE",
17941 "INTERFACE_AGE",
17942 "CORE_ABI",
17943 "PATCH",
17944 "COPYRIGHT",
17945 "TIMESTAMP",
17946 "REVISION",
17947 "PACKAGE_TAG",
17948 "PACKAGEDATE",
17949 "NUMVERSION",
17950 "Release",
17951 "Version"
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040017952);
17953
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017954sub constantFilter($$$)
17955{
17956 my ($Name, $Value, $Level) = @_;
17957
17958 if($Level eq "Binary")
17959 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017960 if($Name=~/_t\Z/)
17961 { # __malloc_ptr_t
17962 return 1;
17963 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017964 foreach (keys(%IgnoreConstant))
17965 {
17966 if($Name=~/(\A|_)$_(_|\Z)/)
17967 { # version
17968 return 1;
17969 }
17970 if(/\A[A-Z].*[a-z]\Z/)
17971 {
17972 if($Name=~/(\A|[a-z])$_([A-Z]|\Z)/)
17973 { # version
17974 return 1;
17975 }
17976 }
17977 }
17978 if($Name=~/(\A|_)(lib|open|)$TargetLibraryShortName(_|)(VERSION|VER|DATE|API|PREFIX)(_|\Z)/i)
17979 { # version
17980 return 1;
17981 }
17982 if($Value=~/\A('|"|)[\/\\]\w+([\/\\]|:|('|"|)\Z)/ or $Value=~/[\/\\]\w+[\/\\]\w+/)
17983 { # /lib64:/usr/lib64:/lib:/usr/lib:/usr/X11R6/lib/Xaw3d ...
17984 return 1;
17985 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017986
17987 if($Value=~/\A["'].*['"]/i)
17988 { # string
17989 return 0;
17990 }
17991
17992 if($Value=~/\A[({]*\s*[a-z_]+\w*(\s+|[\|,])/i)
17993 { # static int gcry_pth_init
17994 # extern ABC
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017995 # (RE_BACKSLASH_ESCAPE_IN_LISTS | RE...
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017996 # { H5FD_MEM_SUPER, H5FD_MEM_SUPER, ...
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040017997 return 1;
17998 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040017999 if($Value=~/\w+\s*\(/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018000 { # foo(p)
18001 return 1;
18002 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018003 if($Value=~/\A[a-z_]+\w*\Z/i)
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018004 { # asn1_node_st
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018005 # __SMTH_P
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018006 return 1;
18007 }
18008 }
18009
18010 return 0;
18011}
18012
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018013sub mergeConstants($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018014{
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018015 my $Level = $_[0];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018016 foreach my $Constant (keys(%{$Constants{1}}))
18017 {
18018 if($SkipConstants{1}{$Constant})
18019 { # skipped by the user
18020 next;
18021 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018022
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018023 if(my $Header = $Constants{1}{$Constant}{"Header"})
18024 {
18025 if(not is_target_header($Header, 1)
18026 and not is_target_header($Header, 2))
18027 { # user-defined header
18028 next;
18029 }
18030 }
18031 else {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018032 next;
18033 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018034
18035 my $Old_Value = uncoverConstant(1, $Constant);
18036
18037 if(constantFilter($Constant, $Old_Value, $Level))
18038 { # separate binary and source problems
18039 next;
18040 }
18041
18042 if(not defined $Constants{2}{$Constant}{"Value"})
18043 { # removed
18044 %{$CompatProblems_Constants{$Level}{$Constant}{"Removed_Constant"}} = (
18045 "Target"=>$Constant,
18046 "Old_Value"=>$Old_Value );
18047 next;
18048 }
18049
18050 if($Constants{2}{$Constant}{"Value"} eq "")
18051 { # empty value
18052 # TODO: implement a rule
18053 next;
18054 }
18055
18056 my $New_Value = uncoverConstant(2, $Constant);
18057
18058 my $Old_Value_Pure = $Old_Value;
18059 my $New_Value_Pure = $New_Value;
18060
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018061 $Old_Value_Pure=~s/(\W)\s+/$1/g;
18062 $Old_Value_Pure=~s/\s+(\W)/$1/g;
18063 $New_Value_Pure=~s/(\W)\s+/$1/g;
18064 $New_Value_Pure=~s/\s+(\W)/$1/g;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018065
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018066 next if($New_Value_Pure eq "" or $Old_Value_Pure eq "");
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018067
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018068 if($New_Value_Pure ne $Old_Value_Pure)
18069 { # different values
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018070 if(simpleConstant(1, $Old_Value) eq simpleConstant(2, $New_Value))
18071 { # complex values
18072 next;
18073 }
18074 if(computeValue($Old_Value) eq computeValue($New_Value))
18075 { # expressions
18076 next;
18077 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018078 if(convert_integer($Old_Value) eq convert_integer($New_Value))
18079 { # 0x0001 and 0x1, 0x1 and 1 equal constants
18080 next;
18081 }
18082 if($Old_Value eq "0" and $New_Value eq "NULL")
18083 { # 0 => NULL
18084 next;
18085 }
18086 if($Old_Value eq "NULL" and $New_Value eq "0")
18087 { # NULL => 0
18088 next;
18089 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018090 %{$CompatProblems_Constants{$Level}{$Constant}{"Changed_Constant"}} = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018091 "Target"=>$Constant,
18092 "Old_Value"=>$Old_Value,
18093 "New_Value"=>$New_Value );
18094 }
18095 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018096
18097 foreach my $Constant (keys(%{$Constants{2}}))
18098 {
18099 if(not defined $Constants{1}{$Constant}{"Value"})
18100 {
18101 if($SkipConstants{2}{$Constant})
18102 { # skipped by the user
18103 next;
18104 }
18105
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018106 if(my $Header = $Constants{2}{$Constant}{"Header"})
18107 {
18108 if(not is_target_header($Header, 1)
18109 and not is_target_header($Header, 2))
18110 { # user-defined header
18111 next;
18112 }
18113 }
18114 else {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018115 next;
18116 }
18117
18118 my $New_Value = uncoverConstant(2, $Constant);
18119 if(not defined $New_Value or $New_Value eq "") {
18120 next;
18121 }
18122
18123 if(constantFilter($Constant, $New_Value, $Level))
18124 { # separate binary and source problems
18125 next;
18126 }
18127
18128 %{$CompatProblems_Constants{$Level}{$Constant}{"Added_Constant"}} = (
18129 "Target"=>$Constant,
18130 "New_Value"=>$New_Value );
18131 }
18132 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018133}
18134
18135sub convert_integer($)
18136{
18137 my $Value = $_[0];
18138 if($Value=~/\A0x[a-f0-9]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018139 { # hexadecimal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018140 return hex($Value);
18141 }
18142 elsif($Value=~/\A0[0-7]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018143 { # octal
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018144 return oct($Value);
18145 }
18146 elsif($Value=~/\A0b[0-1]+\Z/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018147 { # binary
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018148 return oct($Value);
18149 }
18150 else {
18151 return $Value;
18152 }
18153}
18154
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018155sub readSymbols($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018156{
18157 my $LibVersion = $_[0];
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018158 my @LibPaths = getSOPaths($LibVersion);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018159 if($#LibPaths==-1 and not $CheckHeadersOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018160 {
18161 if($LibVersion==1)
18162 {
18163 printMsg("WARNING", "checking headers only");
18164 $CheckHeadersOnly = 1;
18165 }
18166 else {
18167 exitStatus("Error", "$SLIB_TYPE libraries are not found in ".$Descriptor{$LibVersion}{"Version"});
18168 }
18169 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018170
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018171 foreach my $LibPath (@LibPaths) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018172 readSymbols_Lib($LibVersion, $LibPath, 0, "+Weak", 1, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018173 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018174
18175 if($CheckUndefined)
18176 {
18177 my %UndefinedLibs = ();
18178
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018179 my @Libs = (keys(%{$Library_Symbol{$LibVersion}}), keys(%{$DepLibrary_Symbol{$LibVersion}}));
18180
18181 foreach my $LibName (sort @Libs)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018182 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018183 if(defined $UndefinedSymbols{$LibVersion}{$LibName})
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018184 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018185 foreach my $Symbol (keys(%{$UndefinedSymbols{$LibVersion}{$LibName}}))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018186 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018187 if($Symbol_Library{$LibVersion}{$Symbol}
18188 or $DepSymbol_Library{$LibVersion}{$Symbol})
18189 { # exported by target library
18190 next;
18191 }
18192 if(index($Symbol, '@')!=-1)
18193 { # exported default symbol version (@@)
18194 $Symbol=~s/\@/\@\@/;
18195 if($Symbol_Library{$LibVersion}{$Symbol}
18196 or $DepSymbol_Library{$LibVersion}{$Symbol}) {
18197 next;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018198 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018199 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018200 foreach my $Path (find_SymbolLibs($LibVersion, $Symbol)) {
18201 $UndefinedLibs{$Path} = 1;
18202 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018203 }
18204 }
18205 }
18206 if($ExtraInfo)
18207 { # extra information for other tools
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018208 if(my @Paths = sort keys(%UndefinedLibs))
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018209 {
18210 my $LibString = "";
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018211 my %Dirs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018212 foreach (@Paths)
18213 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018214 $KnownLibs{$_} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018215 my ($Dir, $Name) = separate_path($_);
18216
18217 if(not grep {$Dir eq $_} (@{$SystemPaths{"lib"}})) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018218 $Dirs{esc($Dir)} = 1;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018219 }
18220
18221 $Name = parse_libname($Name, "name", $OStarget);
18222 $Name=~s/\Alib//;
18223
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018224 $LibString .= " -l$Name";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018225 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018226
18227 foreach my $Dir (sort {$b cmp $a} keys(%Dirs))
18228 {
18229 $LibString = " -L".esc($Dir).$LibString;
18230 }
18231
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018232 writeFile($ExtraInfo."/libs-string", $LibString);
18233 }
18234 }
18235 }
18236
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018237 if($ExtraInfo) {
18238 writeFile($ExtraInfo."/lib-paths", join("\n", sort keys(%KnownLibs)));
18239 }
18240
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018241 if(not $CheckHeadersOnly)
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018242 {
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018243 if($#LibPaths!=-1)
18244 {
18245 if(not keys(%{$Symbol_Library{$LibVersion}}))
18246 {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040018247 printMsg("WARNING", "the set of public symbols in library(ies) is empty ($LibVersion)");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018248 printMsg("WARNING", "checking headers only");
18249 $CheckHeadersOnly = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018250 }
18251 }
18252 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018253
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018254 # clean memory
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018255 %SystemObjects = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018256}
18257
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018258my %Prefix_Lib_Map=(
18259 # symbols for autodetecting library dependencies (by prefix)
18260 "pthread_" => ["libpthread"],
18261 "g_" => ["libglib-2.0", "libgobject-2.0", "libgio-2.0"],
18262 "cairo_" => ["libcairo"],
18263 "gtk_" => ["libgtk-x11-2.0"],
18264 "atk_" => ["libatk-1.0"],
18265 "gdk_" => ["libgdk-x11-2.0"],
18266 "gl" => ["libGL"],
18267 "glu" => ["libGLU"],
18268 "popt" => ["libpopt"],
18269 "Py" => ["libpython"],
18270 "jpeg_" => ["libjpeg"],
18271 "BZ2_" => ["libbz2"],
18272 "Fc" => ["libfontconfig"],
18273 "Xft" => ["libXft"],
18274 "SSL_" => ["libssl"],
18275 "sem_" => ["libpthread"],
18276 "snd_" => ["libasound"],
18277 "art_" => ["libart_lgpl_2"],
18278 "dbus_g" => ["libdbus-glib-1"],
18279 "GOMP_" => ["libgomp"],
18280 "omp_" => ["libgomp"],
18281 "cms" => ["liblcms"]
18282);
18283
18284my %Pattern_Lib_Map=(
18285 "SL[a-z]" => ["libslang"]
18286);
18287
18288my %Symbol_Lib_Map=(
18289 # symbols for autodetecting library dependencies (by name)
18290 "pow" => "libm",
18291 "fmod" => "libm",
18292 "sin" => "libm",
18293 "floor" => "libm",
18294 "cos" => "libm",
18295 "dlopen" => "libdl",
18296 "deflate" => "libz",
18297 "inflate" => "libz",
18298 "move_panel" => "libpanel",
18299 "XOpenDisplay" => "libX11",
18300 "resize_term" => "libncurses",
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040018301 "clock_gettime" => "librt",
18302 "crypt" => "libcrypt"
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018303);
18304
18305sub find_SymbolLibs($$)
18306{
18307 my ($LibVersion, $Symbol) = @_;
18308
18309 if(index($Symbol, "g_")==0 and $Symbol=~/[A-Z]/)
18310 { # debug symbols
18311 return ();
18312 }
18313
18314 my %Paths = ();
18315
18316 if(my $LibName = $Symbol_Lib_Map{$Symbol})
18317 {
18318 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18319 $Paths{$Path} = 1;
18320 }
18321 }
18322
18323 if(my $SymbolPrefix = getPrefix($Symbol))
18324 {
18325 if(defined $Cache{"find_SymbolLibs"}{$SymbolPrefix}) {
18326 return @{$Cache{"find_SymbolLibs"}{$SymbolPrefix}};
18327 }
18328
18329 if(not keys(%Paths))
18330 {
18331 if(defined $Prefix_Lib_Map{$SymbolPrefix})
18332 {
18333 foreach my $LibName (@{$Prefix_Lib_Map{$SymbolPrefix}})
18334 {
18335 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18336 $Paths{$Path} = 1;
18337 }
18338 }
18339 }
18340 }
18341
18342 if(not keys(%Paths))
18343 {
18344 foreach my $Prefix (sort keys(%Pattern_Lib_Map))
18345 {
18346 if($Symbol=~/\A$Prefix/)
18347 {
18348 foreach my $LibName (@{$Pattern_Lib_Map{$Prefix}})
18349 {
18350 if(my $Path = get_LibPath($LibVersion, $LibName.".".$LIB_EXT)) {
18351 $Paths{$Path} = 1;
18352 }
18353 }
18354 }
18355 }
18356 }
18357
18358 if(not keys(%Paths))
18359 {
18360 if($SymbolPrefix)
18361 { # try to find a library by symbol prefix
18362 if($SymbolPrefix eq "inotify" and
18363 index($Symbol, "\@GLIBC")!=-1)
18364 {
18365 if(my $Path = get_LibPath($LibVersion, "libc.$LIB_EXT")) {
18366 $Paths{$Path} = 1;
18367 }
18368 }
18369 else
18370 {
18371 if(my $Path = get_LibPath_Prefix($LibVersion, $SymbolPrefix)) {
18372 $Paths{$Path} = 1;
18373 }
18374 }
18375 }
18376 }
18377
18378 if(my @Paths = keys(%Paths)) {
18379 $Cache{"find_SymbolLibs"}{$SymbolPrefix} = \@Paths;
18380 }
18381 }
18382 return keys(%Paths);
18383}
18384
18385sub get_LibPath_Prefix($$)
18386{
18387 my ($LibVersion, $Prefix) = @_;
18388
18389 $Prefix = lc($Prefix);
18390 $Prefix=~s/[_]+\Z//g;
18391
18392 foreach ("-2", "2", "-1", "1", "")
18393 { # libgnome-2.so
18394 # libxml2.so
18395 # libdbus-1.so
18396 if(my $Path = get_LibPath($LibVersion, "lib".$Prefix.$_.".".$LIB_EXT)) {
18397 return $Path;
18398 }
18399 }
18400 return "";
18401}
18402
18403sub getPrefix($)
18404{
18405 my $Str = $_[0];
18406 if($Str=~/\A([_]*[A-Z][a-z]{1,5})[A-Z]/)
18407 { # XmuValidArea: Xmu
18408 return $1;
18409 }
18410 elsif($Str=~/\A([_]*[a-z]+)[A-Z]/)
18411 { # snfReadFont: snf
18412 return $1;
18413 }
18414 elsif($Str=~/\A([_]*[A-Z]{2,})[A-Z][a-z]+([A-Z][a-z]+|\Z)/)
18415 { # XRRTimes: XRR
18416 return $1;
18417 }
18418 elsif($Str=~/\A([_]*[a-z]{1,2}\d+)[a-z\d]*_[a-z]+/i)
18419 { # H5HF_delete: H5
18420 return $1;
18421 }
18422 elsif($Str=~/\A([_]*[a-z0-9]{2,}_)[a-z]+/i)
18423 { # alarm_event_add: alarm_
18424 return $1;
18425 }
18426 elsif($Str=~/\A(([a-z])\2{1,})/i)
18427 { # ffopen
18428 return $1;
18429 }
18430 return "";
18431}
18432
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018433sub getSymbolSize($$)
18434{ # size from the shared library
18435 my ($Symbol, $LibVersion) = @_;
18436 return 0 if(not $Symbol);
18437 if(defined $Symbol_Library{$LibVersion}{$Symbol}
18438 and my $LibName = $Symbol_Library{$LibVersion}{$Symbol})
18439 {
18440 if(defined $Library_Symbol{$LibVersion}{$LibName}{$Symbol}
18441 and my $Size = $Library_Symbol{$LibVersion}{$LibName}{$Symbol})
18442 {
18443 if($Size<0) {
18444 return -$Size;
18445 }
18446 }
18447 }
18448 return 0;
18449}
18450
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018451sub canonifyName($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018452{ # make TIFFStreamOpen(char const*, std::basic_ostream<char, std::char_traits<char> >*)
18453 # to be TIFFStreamOpen(char const*, std::basic_ostream<char>*)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018454 my ($Name, $Type) = @_;
18455
18456 # single
18457 while($Name=~/([^<>,]+),\s*$DEFAULT_STD_PARMS<([^<>,]+)>\s*/ and $1 eq $3)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018458 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040018459 my $P = $1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018460 $Name=~s/\Q$P\E,\s*$DEFAULT_STD_PARMS<\Q$P\E>\s*/$P/g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018461 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018462
18463 # double
18464 if($Name=~/$DEFAULT_STD_PARMS/)
18465 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018466 if($Type eq "S")
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018467 {
18468 my ($ShortName, $FuncParams) = split_Signature($Name);
18469
18470 foreach my $FParam (separate_Params($FuncParams, 0, 0))
18471 {
18472 if(index($FParam, "<")!=-1)
18473 {
18474 $FParam=~s/>([^<>]+)\Z/>/; # remove quals
18475 my $FParam_N = canonifyName($FParam, "T");
18476 if($FParam_N ne $FParam) {
18477 $Name=~s/\Q$FParam\E/$FParam_N/g;
18478 }
18479 }
18480 }
18481 }
18482 elsif($Type eq "T")
18483 {
18484 my ($ShortTmpl, $TmplParams) = template_Base($Name);
18485
18486 my @TParams = separate_Params($TmplParams, 0, 0);
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018487 if($#TParams>=1)
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018488 {
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018489 my $FParam = $TParams[0];
18490 foreach my $Pos (1 .. $#TParams)
18491 {
18492 my $TParam = $TParams[$Pos];
18493 if($TParam=~/\A$DEFAULT_STD_PARMS<\Q$FParam\E\s*>\Z/) {
18494 $Name=~s/\Q$FParam, $TParam\E\s*/$FParam/g;
18495 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018496 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018497 }
18498 }
18499 }
Andrey Ponomarenkoe3d6bf02012-11-14 11:49:09 +040018500 if($Type eq "S") {
18501 return formatName($Name, "S");
18502 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018503 return $Name;
18504}
18505
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018506sub translateSymbols(@)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018507{
18508 my $LibVersion = pop(@_);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018509 my (@MnglNames1, @MnglNames2, @UnmangledNames) = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018510 foreach my $Symbol (sort @_)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018511 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018512 if(index($Symbol, "_Z")==0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018513 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018514 next if($tr_name{$Symbol});
18515 $Symbol=~s/[\@\$]+(.*)\Z//;
18516 push(@MnglNames1, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018517 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018518 elsif(index($Symbol, "?")==0)
18519 {
18520 next if($tr_name{$Symbol});
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018521 push(@MnglNames2, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018522 }
18523 else
18524 { # not mangled
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018525 $tr_name{$Symbol} = $Symbol;
18526 $mangled_name_gcc{$Symbol} = $Symbol;
18527 $mangled_name{$LibVersion}{$Symbol} = $Symbol;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018528 }
18529 }
18530 if($#MnglNames1 > -1)
18531 { # GCC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018532 @UnmangledNames = reverse(unmangleArray(@MnglNames1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018533 foreach my $MnglName (@MnglNames1)
18534 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018535 if(my $Unmangled = pop(@UnmangledNames))
18536 {
Andrey Ponomarenko72930b92012-11-14 12:09:17 +040018537 $tr_name{$MnglName} = canonifyName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018538 if(not $mangled_name_gcc{$tr_name{$MnglName}}) {
18539 $mangled_name_gcc{$tr_name{$MnglName}} = $MnglName;
18540 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018541 if(index($MnglName, "_ZTV")==0
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018542 and $tr_name{$MnglName}=~/vtable for (.+)/)
18543 { # bind class name and v-table symbol
18544 my $ClassName = $1;
18545 $ClassVTable{$ClassName} = $MnglName;
18546 $VTableClass{$MnglName} = $ClassName;
18547 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018548 }
18549 }
18550 }
18551 if($#MnglNames2 > -1)
18552 { # MSVC names
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018553 @UnmangledNames = reverse(unmangleArray(@MnglNames2));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018554 foreach my $MnglName (@MnglNames2)
18555 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018556 if(my $Unmangled = pop(@UnmangledNames))
18557 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018558 $tr_name{$MnglName} = formatName($Unmangled, "S");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018559 $mangled_name{$LibVersion}{$tr_name{$MnglName}} = $MnglName;
18560 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018561 }
18562 }
18563 return \%tr_name;
18564}
18565
18566sub link_symbol($$$)
18567{
18568 my ($Symbol, $RunWith, $Deps) = @_;
18569 if(link_symbol_internal($Symbol, $RunWith, \%Symbol_Library)) {
18570 return 1;
18571 }
18572 if($Deps eq "+Deps")
18573 { # check the dependencies
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018574 if(link_symbol_internal($Symbol, $RunWith, \%DepSymbol_Library)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018575 return 1;
18576 }
18577 }
18578 return 0;
18579}
18580
18581sub link_symbol_internal($$$)
18582{
18583 my ($Symbol, $RunWith, $Where) = @_;
18584 return 0 if(not $Where or not $Symbol);
18585 if($Where->{$RunWith}{$Symbol})
18586 { # the exact match by symbol name
18587 return 1;
18588 }
18589 if(my $VSym = $SymVer{$RunWith}{$Symbol})
18590 { # indirect symbol version, i.e.
18591 # foo_old and its symlink foo@v (or foo@@v)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018592 # foo_old may be in symtab table
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018593 if($Where->{$RunWith}{$VSym}) {
18594 return 1;
18595 }
18596 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018597 my ($Sym, $Spec, $Ver) = separate_symbol($Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018598 if($Sym and $Ver)
18599 { # search for the symbol with the same version
18600 # or without version
18601 if($Where->{$RunWith}{$Sym})
18602 { # old: foo@v|foo@@v
18603 # new: foo
18604 return 1;
18605 }
18606 if($Where->{$RunWith}{$Sym."\@".$Ver})
18607 { # old: foo|foo@@v
18608 # new: foo@v
18609 return 1;
18610 }
18611 if($Where->{$RunWith}{$Sym."\@\@".$Ver})
18612 { # old: foo|foo@v
18613 # new: foo@@v
18614 return 1;
18615 }
18616 }
18617 return 0;
18618}
18619
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018620sub readSymbols_App($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018621{
18622 my $Path = $_[0];
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018623 return () if(not $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018624 my @Imported = ();
18625 if($OSgroup eq "macos")
18626 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018627 my $NM = get_CmdPath("nm");
18628 if(not $NM) {
18629 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018630 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018631 open(APP, "$NM -g \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018632 while(<APP>)
18633 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018634 if(/ U _([\w\$]+)\s*\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018635 push(@Imported, $1);
18636 }
18637 }
18638 close(APP);
18639 }
18640 elsif($OSgroup eq "windows")
18641 {
18642 my $DumpBinCmd = get_CmdPath("dumpbin");
18643 if(not $DumpBinCmd) {
18644 exitStatus("Not_Found", "can't find \"dumpbin.exe\"");
18645 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018646 open(APP, "$DumpBinCmd /IMPORTS \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018647 while(<APP>)
18648 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018649 if(/\s*\w+\s+\w+\s+\w+\s+([\w\?\@]+)\s*/) {
18650 push(@Imported, $1);
18651 }
18652 }
18653 close(APP);
18654 }
18655 else
18656 {
18657 my $ReadelfCmd = get_CmdPath("readelf");
18658 if(not $ReadelfCmd) {
18659 exitStatus("Not_Found", "can't find \"readelf\"");
18660 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018661 open(APP, "$ReadelfCmd -WhlSsdA \"$Path\" 2>\"$TMP_DIR/null\" |");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018662 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018663 while(<APP>)
18664 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018665 if(defined $symtab)
18666 { # do nothing with symtab
18667 if(index($_, "'.dynsym'")!=-1)
18668 { # dynamic table
18669 $symtab = undef;
18670 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018671 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018672 elsif(index($_, "'.symtab'")!=-1)
18673 { # symbol table
18674 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018675 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018676 elsif(my @Info = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018677 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018678 my ($Ndx, $Symbol) = ($Info[5], $Info[6]);
18679 if($Ndx eq "UND")
18680 { # only imported symbols
18681 push(@Imported, $Symbol);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018682 }
18683 }
18684 }
18685 close(APP);
18686 }
18687 return @Imported;
18688}
18689
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018690my %ELF_BIND = map {$_=>1} (
18691 "WEAK",
18692 "GLOBAL"
18693);
18694
18695my %ELF_TYPE = map {$_=>1} (
18696 "FUNC",
18697 "IFUNC",
18698 "OBJECT",
18699 "COMMON"
18700);
18701
18702my %ELF_VIS = map {$_=>1} (
18703 "DEFAULT",
18704 "PROTECTED"
18705);
18706
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018707sub readline_ELF($)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018708{ # read the line of 'readelf' output corresponding to the symbol
18709 my @Info = split(/\s+/, $_[0]);
18710 # Num: Value Size Type Bind Vis Ndx Name
18711 # 3629: 000b09c0 32 FUNC GLOBAL DEFAULT 13 _ZNSt12__basic_fileIcED1Ev@@GLIBCXX_3.4
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018712 # 135: 00000000 0 FUNC GLOBAL DEFAULT UND av_image_fill_pointers@LIBAVUTIL_52 (3)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018713 shift(@Info); # spaces
18714 shift(@Info); # num
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018715
18716 if($#Info==7)
18717 { # UND SYMBOL (N)
18718 if($Info[7]=~/\(\d+\)/) {
18719 pop(@Info);
18720 }
18721 }
18722
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018723 if($#Info!=6)
18724 { # other lines
18725 return ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018726 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018727 return () if(not defined $ELF_TYPE{$Info[2]} and $Info[5] ne "UND");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018728 return () if(not defined $ELF_BIND{$Info[3]});
18729 return () if(not defined $ELF_VIS{$Info[4]});
18730 if($Info[5] eq "ABS" and $Info[0]=~/\A0+\Z/)
18731 { # 1272: 00000000 0 OBJECT GLOBAL DEFAULT ABS CXXABI_1.3
18732 return ();
18733 }
18734 if($OStarget eq "symbian")
18735 { # _ZN12CCTTokenType4NewLE4TUid3RFs@@ctfinder{000a0000}[102020e5].dll
18736 if(index($Info[6], "_._.absent_export_")!=-1)
18737 { # "_._.absent_export_111"@@libstdcpp{00010001}[10282872].dll
18738 return ();
18739 }
18740 $Info[6]=~s/\@.+//g; # remove version
18741 }
18742 if(index($Info[2], "0x") == 0)
18743 { # size == 0x3d158
18744 $Info[2] = hex($Info[2]);
18745 }
18746 return @Info;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018747}
18748
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018749sub get_LibPath($$)
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018750{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018751 my ($LibVersion, $Name) = @_;
18752 return "" if(not $LibVersion or not $Name);
18753 if(defined $Cache{"get_LibPath"}{$LibVersion}{$Name}) {
18754 return $Cache{"get_LibPath"}{$LibVersion}{$Name};
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018755 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018756 return ($Cache{"get_LibPath"}{$LibVersion}{$Name} = get_LibPath_I($LibVersion, $Name));
18757}
18758
18759sub get_LibPath_I($$)
18760{
18761 my ($LibVersion, $Name) = @_;
18762 if(is_abs($Name))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018763 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018764 if(-f $Name)
18765 { # absolute path
18766 return $Name;
18767 }
18768 else
18769 { # broken
18770 return "";
18771 }
18772 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018773 if(defined $RegisteredObjects{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018774 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018775 return $RegisteredObjects{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018776 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018777 if(defined $RegisteredSONAMEs{$LibVersion}{$Name})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018778 { # registered paths
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018779 return $RegisteredSONAMEs{$LibVersion}{$Name};
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018780 }
18781 if(my $DefaultPath = $DyLib_DefaultPath{$Name})
18782 { # ldconfig default paths
18783 return $DefaultPath;
18784 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018785 foreach my $Dir (@DefaultLibPaths, @{$SystemPaths{"lib"}})
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018786 { # search in default linker directories
18787 # and then in all system paths
18788 if(-f $Dir."/".$Name) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018789 return join_P($Dir,$Name);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018790 }
18791 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040018792 if(not defined $Cache{"checkSystemFiles"}) {
18793 checkSystemFiles();
18794 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018795 if(my @AllObjects = keys(%{$SystemObjects{$Name}})) {
18796 return $AllObjects[0];
18797 }
18798 if(my $ShortName = parse_libname($Name, "name+ext", $OStarget))
18799 {
18800 if($ShortName ne $Name)
18801 { # FIXME: check this case
18802 if(my $Path = get_LibPath($LibVersion, $ShortName)) {
18803 return $Path;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018804 }
18805 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018806 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018807 # can't find
18808 return "";
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018809}
18810
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018811sub readSymbols_Lib($$$$$$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018812{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018813 my ($LibVersion, $Lib_Path, $IsNeededLib, $Weak, $Deps, $Vers) = @_;
18814 return () if(not $LibVersion or not $Lib_Path);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018815
18816 my $Real_Path = realpath($Lib_Path);
18817
18818 if(not $Real_Path)
18819 { # broken link
18820 return ();
18821 }
18822
18823 my $Lib_Name = get_filename($Real_Path);
18824
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018825 if($ExtraInfo)
18826 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018827 $KnownLibs{$Real_Path} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040018828 $KnownLibs{$Lib_Path} = 1; # links
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018829 }
18830
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018831 if($IsNeededLib)
18832 {
18833 if($CheckedDyLib{$LibVersion}{$Lib_Name}) {
18834 return ();
18835 }
18836 }
18837 return () if(isCyclical(\@RecurLib, $Lib_Name) or $#RecurLib>=1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018838 $CheckedDyLib{$LibVersion}{$Lib_Name} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018839
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018840 if($CheckImpl)
18841 {
18842 if(not $IsNeededLib) {
18843 getImplementations($LibVersion, $Lib_Path);
18844 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018845 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018846
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018847 push(@RecurLib, $Lib_Name);
18848 my (%Value_Interface, %Interface_Value, %NeededLib) = ();
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018849 my $Lib_ShortName = parse_libname($Lib_Name, "name+ext", $OStarget);
18850
18851 if(not $IsNeededLib)
18852 { # special cases: libstdc++ and libc
18853 if(my $ShortName = parse_libname($Lib_Name, "short", $OStarget))
18854 {
18855 if($ShortName eq "libstdc++")
18856 { # libstdc++.so.6
18857 $STDCXX_TESTING = 1;
18858 }
18859 elsif($ShortName eq "libc")
18860 { # libc-2.11.3.so
18861 $GLIBC_TESTING = 1;
18862 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018863 }
18864 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018865 my $DebugPath = "";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018866 if($Debug and not $DumpSystem)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018867 { # debug mode
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040018868 $DebugPath = $DEBUG_PATH{$LibVersion}."/libs/".get_filename($Lib_Path).".txt";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018869 mkpath(get_dirname($DebugPath));
18870 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018871 if($OStarget eq "macos")
18872 { # Mac OS X: *.dylib, *.a
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018873 my $NM = get_CmdPath("nm");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018874 if(not $NM) {
18875 exitStatus("Not_Found", "can't find \"nm\"");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018876 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018877 $NM .= " -g \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018878 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018879 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018880 # write to file
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018881 system($NM." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018882 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018883 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018884 else
18885 { # write to pipe
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018886 open(LIB, $NM." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018887 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018888 while(<LIB>)
18889 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018890 if($CheckUndefined)
18891 {
18892 if(not $IsNeededLib)
18893 {
18894 if(/ U _([\w\$]+)\s*\Z/)
18895 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040018896 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$1} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018897 next;
18898 }
18899 }
18900 }
18901
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018902 if(/ [STD] _([\w\$]+)\s*\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018903 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018904 my $Symbol = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018905 if($IsNeededLib)
18906 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018907 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018908 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018909 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18910 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018911 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018912 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018913 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018914 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018915 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
18916 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018917 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18918 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018919 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018920 setLanguage($LibVersion, "C++");
18921 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018922 }
18923 if($CheckObjectsOnly
18924 and $LibVersion==1) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040018925 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018926 }
18927 }
18928 }
18929 }
18930 close(LIB);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018931
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018932 if($Deps)
18933 {
18934 if($LIB_TYPE eq "dynamic")
18935 { # dependencies
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018936
18937 my $OtoolCmd = get_CmdPath("otool");
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040018938 if(not $OtoolCmd) {
18939 exitStatus("Not_Found", "can't find \"otool\"");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040018940 }
18941
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018942 open(LIB, "$OtoolCmd -L \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
18943 while(<LIB>)
18944 {
18945 if(/\s*([\/\\].+\.$LIB_EXT)\s*/
18946 and $1 ne $Lib_Path) {
18947 $NeededLib{$1} = 1;
18948 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018949 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018950 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018951 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018952 }
18953 }
18954 elsif($OStarget eq "windows")
18955 { # Windows *.dll, *.lib
18956 my $DumpBinCmd = get_CmdPath("dumpbin");
18957 if(not $DumpBinCmd) {
18958 exitStatus("Not_Found", "can't find \"dumpbin\"");
18959 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018960 $DumpBinCmd .= " /EXPORTS \"".$Lib_Path."\" 2>$TMP_DIR/null";
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018961 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018962 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018963 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040018964 system($DumpBinCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018965 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018966 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040018967 else
18968 { # write to pipe
18969 open(LIB, $DumpBinCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040018970 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018971 while(<LIB>)
18972 { # 1197 4AC 0000A620 SetThreadStackGuarantee
18973 # 1198 4AD SetThreadToken (forwarded to ...)
18974 # 3368 _o2i_ECPublicKey
18975 if(/\A\s*\d+\s+[a-f\d]+\s+[a-f\d]+\s+([\w\?\@]+)\s*\Z/i
18976 or /\A\s*\d+\s+[a-f\d]+\s+([\w\?\@]+)\s*\(\s*forwarded\s+/
18977 or /\A\s*\d+\s+_([\w\?\@]+)\s*\Z/)
18978 { # dynamic, static and forwarded symbols
18979 my $realname = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018980 if($IsNeededLib)
18981 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040018982 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018983 {
18984 $DepSymbol_Library{$LibVersion}{$realname} = $Lib_Name;
18985 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
18986 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018987 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040018988 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018989 {
18990 $Symbol_Library{$LibVersion}{$realname} = $Lib_Name;
18991 $Library_Symbol{$LibVersion}{$Lib_Name}{$realname} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040018992 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
18993 {
18994 if(index($realname, "_Z")==0 or index($realname, "?")==0) {
18995 setLanguage($LibVersion, "C++");
18996 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040018997 }
18998 if($CheckObjectsOnly
18999 and $LibVersion==1) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019000 $CheckedSymbols{"Binary"}{$realname} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019001 }
19002 }
19003 }
19004 }
19005 close(LIB);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019006 if($Deps)
19007 {
19008 if($LIB_TYPE eq "dynamic")
19009 { # dependencies
19010 open(LIB, "$DumpBinCmd /DEPENDENTS \"$Lib_Path\" 2>\"$TMP_DIR/null\" |");
19011 while(<LIB>)
19012 {
19013 if(/\s*([^\s]+?\.$LIB_EXT)\s*/i
19014 and $1 ne $Lib_Path) {
19015 $NeededLib{path_format($1, $OSgroup)} = 1;
19016 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019017 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019018 close(LIB);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019019 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019020 }
19021 }
19022 else
19023 { # Unix; *.so, *.a
19024 # Symbian: *.dso, *.lib
19025 my $ReadelfCmd = get_CmdPath("readelf");
19026 if(not $ReadelfCmd) {
19027 exitStatus("Not_Found", "can't find \"readelf\"");
19028 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019029 $ReadelfCmd .= " -WhlSsdA \"$Lib_Path\" 2>\"$TMP_DIR/null\"";
19030 if($DebugPath)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019031 { # debug mode
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019032 # write to file
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019033 system($ReadelfCmd." >\"$DebugPath\"");
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019034 open(LIB, $DebugPath);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019035 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040019036 else
19037 { # write to pipe
19038 open(LIB, $ReadelfCmd." |");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019039 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019040 my $symtab = undef; # indicates that we are processing 'symtab' section of 'readelf' output
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019041 while(<LIB>)
19042 {
19043 if($LIB_TYPE eq "dynamic")
19044 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019045 if(defined $symtab)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019046 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019047 if(index($_, "'.dynsym'")!=-1)
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019048 { # dynamic table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019049 $symtab = undef;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019050 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019051 # do nothing with symtab
19052 next;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019053 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019054 elsif(index($_, "'.symtab'")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019055 { # symbol table
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019056 $symtab = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019057 next;
19058 }
19059 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019060 if(my ($Value, $Size, $Type, $Bind, $Vis, $Ndx, $Symbol) = readline_ELF($_))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019061 { # read ELF entry
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019062 if($Ndx eq "UND")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019063 { # ignore interfaces that are imported from somewhere else
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019064 if($CheckUndefined)
19065 {
19066 if(not $IsNeededLib) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019067 $UndefinedSymbols{$LibVersion}{$Lib_Name}{$Symbol} = 0;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019068 }
19069 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019070 next;
19071 }
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019072 if($Bind eq "WEAK")
19073 {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019074 $WeakSymbols{$LibVersion}{$Symbol} = 1;
Andrey Ponomarenkoc593c322013-05-31 17:54:08 +040019075 if($Weak eq "-Weak")
19076 { # skip WEAK symbols
19077 next;
19078 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019079 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019080 my $Short = $Symbol;
19081 $Short=~s/\@.+//g;
19082 if($Type eq "OBJECT")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019083 { # global data
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019084 $GlobalDataObject{$LibVersion}{$Symbol} = $Size;
19085 $GlobalDataObject{$LibVersion}{$Short} = $Size;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019086 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019087 if($IsNeededLib)
19088 {
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019089 if(not defined $RegisteredObjects_Short{$LibVersion}{$Lib_ShortName})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019090 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019091 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19092 $DepLibrary_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019093 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019094 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019095 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019096 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019097 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19098 $Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol} = ($Type eq "OBJECT")?-$Size:1;
19099 if($Vers)
19100 {
19101 if($LIB_EXT eq "so")
19102 { # value
19103 $Interface_Value{$LibVersion}{$Symbol} = $Value;
19104 $Value_Interface{$LibVersion}{$Value}{$Symbol} = 1;
19105 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019106 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019107 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19108 {
19109 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19110 setLanguage($LibVersion, "C++");
19111 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019112 }
19113 if($CheckObjectsOnly
19114 and $LibVersion==1) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019115 $CheckedSymbols{"Binary"}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019116 }
19117 }
19118 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019119 elsif($LIB_TYPE eq "dynamic")
19120 { # dynamic library specifics
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019121 if($Deps)
19122 {
19123 if(/NEEDED.+\[([^\[\]]+)\]/)
19124 { # dependencies:
19125 # 0x00000001 (NEEDED) Shared library: [libc.so.6]
19126 $NeededLib{$1} = 1;
19127 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019128 }
19129 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019130 }
19131 close(LIB);
19132 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019133 if($Vers)
19134 {
19135 if(not $IsNeededLib and $LIB_EXT eq "so")
19136 { # get symbol versions
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019137 my %Found = ();
19138
19139 # by value
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019140 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019141 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019142 next if(index($Symbol,"\@")==-1);
19143 if(my $Value = $Interface_Value{$LibVersion}{$Symbol})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019144 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019145 foreach my $Symbol_SameValue (keys(%{$Value_Interface{$LibVersion}{$Value}}))
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019146 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019147 if($Symbol_SameValue ne $Symbol
19148 and index($Symbol_SameValue,"\@")==-1)
19149 {
19150 $SymVer{$LibVersion}{$Symbol_SameValue} = $Symbol;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019151 $Found{$Symbol} = 1;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019152 last;
19153 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019154 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019155 }
19156 }
19157
19158 # default
19159 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19160 {
19161 next if(defined $Found{$Symbol});
19162 next if(index($Symbol,"\@\@")==-1);
19163
19164 if($Symbol=~/\A([^\@]*)\@\@/
19165 and not $SymVer{$LibVersion}{$1})
19166 {
19167 $SymVer{$LibVersion}{$1} = $Symbol;
19168 $Found{$Symbol} = 1;
19169 }
19170 }
19171
19172 # non-default
19173 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
19174 {
19175 next if(defined $Found{$Symbol});
19176 next if(index($Symbol,"\@")==-1);
19177
19178 if($Symbol=~/\A([^\@]*)\@([^\@]*)/
19179 and not $SymVer{$LibVersion}{$1})
19180 {
19181 $SymVer{$LibVersion}{$1} = $Symbol;
19182 $Found{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019183 }
19184 }
19185 }
19186 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019187 if($Deps)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019188 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019189 foreach my $DyLib (sort keys(%NeededLib))
19190 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019191 $Library_Needed{$LibVersion}{$Lib_Name}{get_filename($DyLib)} = 1;
19192
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019193 if(my $DepPath = get_LibPath($LibVersion, $DyLib))
19194 {
19195 if(not $CheckedDyLib{$LibVersion}{get_filename($DepPath)}) {
19196 readSymbols_Lib($LibVersion, $DepPath, 1, "+Weak", $Deps, $Vers);
19197 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019198 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019199 }
19200 }
19201 pop(@RecurLib);
19202 return $Library_Symbol{$LibVersion};
19203}
19204
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019205sub get_prefixes($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019206{
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019207 my %Prefixes = ();
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019208 get_prefixes_I([$_[0]], \%Prefixes);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019209 return keys(%Prefixes);
19210}
19211
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019212sub get_prefixes_I($$)
19213{
19214 foreach my $P (@{$_[0]})
19215 {
19216 my @Parts = reverse(split(/[\/\\]+/, $P));
19217 my $Name = $Parts[0];
19218 foreach (1 .. $#Parts)
19219 {
19220 $_[1]->{$Name}{$P} = 1;
19221 last if($_>4 or $Parts[$_] eq "include");
19222 $Name = $Parts[$_].$SLASH.$Name;
19223 }
19224 }
19225}
19226
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019227sub checkSystemFiles()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019228{
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019229 $Cache{"checkSystemFiles"} = 1;
19230
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019231 my @SysHeaders = ();
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019232
19233 foreach my $DevelPath (@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019234 {
19235 next if(not -d $DevelPath);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019236
19237 my @Files = cmd_find($DevelPath);
19238
19239 if(not $CheckObjectsOnly)
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019240 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019241 # search for headers in /usr/lib
Andrey Ponomarenko13bb0332013-06-28 15:32:28 +040019242 my @Headers = grep { /\.h(pp|xx)?\Z|\/include\// } @Files;
19243 @Headers = grep { not /\/(gcc|jvm|syslinux|kbd|parrot|xemacs|perl|llvm)/ } @Headers;
19244 push(@SysHeaders, @Headers);
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019245 }
19246
19247 # search for libraries in /usr/lib (including symbolic links)
19248 my @Libs = grep { /\.$LIB_EXT[0-9.]*\Z/ } @Files;
19249 foreach my $Path (@Libs)
19250 {
19251 my $N = get_filename($Path);
19252 $SystemObjects{$N}{$Path} = 1;
19253 $SystemObjects{parse_libname($N, "name+ext", $OStarget)}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019254 }
19255 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019256
19257 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019258 {
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019259 foreach my $DevelPath (@{$SystemPaths{"include"}})
19260 {
19261 next if(not -d $DevelPath);
19262 # search for all header files in the /usr/include
19263 # with or without extension (ncurses.h, QtCore, ...)
19264 push(@SysHeaders, cmd_find($DevelPath,"f"));
19265 foreach my $Link (cmd_find($DevelPath,"l"))
19266 { # add symbolic links
19267 if(-f $Link) {
19268 push(@SysHeaders, $Link);
19269 }
19270 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019271 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040019272 get_prefixes_I(\@SysHeaders, \%SystemHeaders);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019273 }
19274}
19275
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019276sub getSOPaths($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019277{
19278 my $LibVersion = $_[0];
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019279 my @Paths = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019280 foreach my $Dest (split(/\s*\n\s*/, $Descriptor{$LibVersion}{"Libs"}))
19281 {
19282 if(not -e $Dest) {
19283 exitStatus("Access_Error", "can't access \'$Dest\'");
19284 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019285 $Dest = get_abs_path($Dest);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019286 my @SoPaths_Dest = getSOPaths_Dest($Dest, $LibVersion);
19287 foreach (@SoPaths_Dest) {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019288 push(@Paths, $_);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019289 }
19290 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040019291 return sort @Paths;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019292}
19293
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019294sub skipLib($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019295{
19296 my ($Path, $LibVersion) = @_;
19297 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019298 my $Name = get_filename($Path);
19299 if($SkipLibs{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019300 return 1;
19301 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019302 my $ShortName = parse_libname($Name, "name+ext", $OStarget);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019303 if($SkipLibs{$LibVersion}{"Name"}{$ShortName}) {
19304 return 1;
19305 }
19306 foreach my $Dir (keys(%{$SkipLibs{$LibVersion}{"Path"}}))
19307 {
19308 if($Path=~/\Q$Dir\E([\/\\]|\Z)/) {
19309 return 1;
19310 }
19311 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019312 foreach my $P (keys(%{$SkipLibs{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019313 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019314 if($Name=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019315 return 1;
19316 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019317 if($P=~/[\/\\]/ and $Path=~/$P/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019318 return 1;
19319 }
19320 }
19321 return 0;
19322}
19323
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019324sub specificHeader($$)
19325{
19326 my ($Header, $Spec) = @_;
19327 my $Name = get_filename($Header);
19328
19329 if($Spec eq "windows")
19330 {# MS Windows
19331 return 1 if($Name=~/(\A|[._-])(win|wince|wnt)(\d\d|[._-]|\Z)/i);
19332 return 1 if($Name=~/([._-]w|win)(32|64)/i);
19333 return 1 if($Name=~/\A(Win|Windows)[A-Z]/);
19334 return 1 if($Name=~/\A(w|win|windows)(32|64|\.)/i);
19335 my @Dirs = (
19336 "win32",
19337 "win64",
19338 "win",
19339 "windows",
19340 "msvcrt"
19341 ); # /gsf-win32/
19342 if(my $DIRs = join("|", @Dirs)) {
19343 return 1 if($Header=~/[\/\\](|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19344 }
19345 }
19346 elsif($Spec eq "macos")
19347 { # Mac OS
19348 return 1 if($Name=~/(\A|[_-])mac[._-]/i);
19349 }
19350
19351 return 0;
19352}
19353
19354sub skipAlienHeader($)
19355{
19356 my $Path = $_[0];
19357 my $Name = get_filename($Path);
19358 my $Dir = get_dirname($Path);
19359
19360 if($Tolerance=~/2/)
19361 { # 2 - skip internal headers
19362 my @Terms = (
19363 "p",
19364 "priv",
19365 "int",
19366 "impl",
19367 "implementation",
19368 "internal",
19369 "private",
19370 "old",
19371 "compat",
19372 "debug",
19373 "test",
19374 "gen"
19375 );
19376
19377 my @Dirs = (
19378 "private",
19379 "priv",
19380 "port",
19381 "impl",
19382 "internal",
19383 "detail",
19384 "details",
19385 "old",
19386 "compat",
19387 "debug",
19388 "config",
19389 "compiler",
19390 "platform",
19391 "test"
19392 );
19393
19394 if(my $TERMs = join("|", @Terms)) {
19395 return 1 if($Name=~/(\A|[._-])($TERMs)([._-]|\Z)/i);
19396 }
19397 if(my $DIRs = join("|", @Dirs)) {
19398 return 1 if($Dir=~/(\A|[\/\\])(|[^\/\\]+[._-])($DIRs)(|[._-][^\/\\]+)([\/\\]|\Z)/i);
19399 }
19400
19401 return 1 if($Name=~/[a-z](Imp|Impl|I|P)(\.|\Z)/);
19402 }
19403
19404 if($Tolerance=~/1/)
19405 { # 1 - skip non-Linux headers
19406 if($OSgroup ne "windows")
19407 {
19408 if(specificHeader($Path, "windows")) {
19409 return 1;
19410 }
19411 }
19412 if($OSgroup ne "macos")
19413 {
19414 if(specificHeader($Path, "macos")) {
19415 return 1;
19416 }
19417 }
19418 }
19419
19420 # valid
19421 return 0;
19422}
19423
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019424sub skipHeader($$)
19425{
19426 my ($Path, $LibVersion) = @_;
19427 return 1 if(not $Path or not $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019428 if(defined $Cache{"skipHeader"}{$Path}) {
19429 return $Cache{"skipHeader"}{$Path};
19430 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019431 if(defined $Tolerance and $Tolerance=~/1|2/)
19432 { # --tolerant
19433 if(skipAlienHeader($Path)) {
19434 return ($Cache{"skipHeader"}{$Path} = 1);
19435 }
19436 }
19437 if(not keys(%{$SkipHeaders{$LibVersion}})) {
19438 return 0;
19439 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019440 return ($Cache{"skipHeader"}{$Path} = skipHeader_I(@_));
19441}
19442
19443sub skipHeader_I($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019444{ # returns:
19445 # 1 - if header should NOT be included and checked
19446 # 2 - if header should NOT be included, but should be checked
19447 my ($Path, $LibVersion) = @_;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019448 my $Name = get_filename($Path);
19449 if(my $Kind = $SkipHeaders{$LibVersion}{"Name"}{$Name}) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019450 return $Kind;
19451 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019452 foreach my $D (keys(%{$SkipHeaders{$LibVersion}{"Path"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019453 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019454 if(index($Path, $D)!=-1)
19455 {
19456 if($Path=~/\Q$D\E([\/\\]|\Z)/) {
19457 return $SkipHeaders{$LibVersion}{"Path"}{$D};
19458 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019459 }
19460 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019461 foreach my $P (keys(%{$SkipHeaders{$LibVersion}{"Pattern"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019462 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019463 if(my $Kind = $SkipHeaders{$LibVersion}{"Pattern"}{$P})
19464 {
19465 if($Name=~/$P/) {
19466 return $Kind;
19467 }
19468 if($P=~/[\/\\]/ and $Path=~/$P/) {
19469 return $Kind;
19470 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019471 }
19472 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019473
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019474 return 0;
19475}
19476
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019477sub registerObject_Dir($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019478{
19479 my ($Dir, $LibVersion) = @_;
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019480 if(grep {$_ eq $Dir} @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019481 { # system directory
19482 return;
19483 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019484 if($RegisteredObject_Dirs{$LibVersion}{$Dir})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019485 { # already registered
19486 return;
19487 }
19488 foreach my $Path (find_libs($Dir,"",1))
19489 {
19490 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019491 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019492 registerObject($Path, $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019493 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019494 $RegisteredObject_Dirs{$LibVersion}{$Dir} = 1;
19495}
19496
19497sub registerObject($$)
19498{
19499 my ($Path, $LibVersion) = @_;
19500 my $Name = get_filename($Path);
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040019501 $RegisteredObjects{$LibVersion}{$Name} = $Path;
Andrey Ponomarenko27681702012-11-12 16:33:39 +040019502 if($OSgroup=~/linux|bsd/i)
19503 {
19504 if(my $SONAME = getSONAME($Path)) {
19505 $RegisteredSONAMEs{$LibVersion}{$SONAME} = $Path;
19506 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019507 }
Andrey Ponomarenko57a405d2012-11-15 11:34:08 +040019508 if(my $Short = parse_libname($Name, "name+ext", $OStarget)) {
19509 $RegisteredObjects_Short{$LibVersion}{$Short} = $Path;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019510 }
19511}
19512
19513sub getSONAME($)
19514{
19515 my $Path = $_[0];
19516 return if(not $Path);
19517 if(defined $Cache{"getSONAME"}{$Path}) {
19518 return $Cache{"getSONAME"}{$Path};
19519 }
19520 my $ObjdumpCmd = get_CmdPath("objdump");
19521 if(not $ObjdumpCmd) {
19522 exitStatus("Not_Found", "can't find \"objdump\"");
19523 }
19524 my $SonameCmd = "$ObjdumpCmd -x $Path 2>$TMP_DIR/null";
19525 if($OSgroup eq "windows") {
19526 $SonameCmd .= " | find \"SONAME\"";
19527 }
19528 else {
19529 $SonameCmd .= " | grep SONAME";
19530 }
19531 if(my $SonameInfo = `$SonameCmd`) {
19532 if($SonameInfo=~/SONAME\s+([^\s]+)/) {
19533 return ($Cache{"getSONAME"}{$Path} = $1);
19534 }
19535 }
19536 return ($Cache{"getSONAME"}{$Path}="");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019537}
19538
19539sub getSOPaths_Dest($$)
19540{
19541 my ($Dest, $LibVersion) = @_;
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019542 if(skipLib($Dest, $LibVersion)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019543 return ();
19544 }
19545 if(-f $Dest)
19546 {
19547 if(not parse_libname($Dest, "name", $OStarget)) {
19548 exitStatus("Error", "incorrect format of library (should be *.$LIB_EXT): \'$Dest\'");
19549 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019550 registerObject($Dest, $LibVersion);
19551 registerObject_Dir(get_dirname($Dest), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019552 return ($Dest);
19553 }
19554 elsif(-d $Dest)
19555 {
19556 $Dest=~s/[\/\\]+\Z//g;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019557 my %Libs = ();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019558 if(grep { $Dest eq $_ } @{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019559 { # you have specified /usr/lib as the search directory (<libs>) in the XML descriptor
19560 # and the real name of the library by -l option (bz2, stdc++, Xaw, ...)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019561 foreach my $Path (cmd_find($Dest,"","*".esc($TargetLibraryName)."*.$LIB_EXT*",2))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019562 { # all files and symlinks that match the name of a library
19563 if(get_filename($Path)=~/\A(|lib)\Q$TargetLibraryName\E[\d\-]*\.$LIB_EXT[\d\.]*\Z/i)
19564 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019565 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019566 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019567 }
19568 }
19569 }
19570 else
19571 { # search for all files and symlinks
19572 foreach my $Path (find_libs($Dest,"",""))
19573 {
19574 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019575 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019576 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019577 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019578 }
19579 if($OSgroup eq "macos")
19580 { # shared libraries on MacOS X may have no extension
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019581 foreach my $Path (cmd_find($Dest,"f"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019582 {
19583 next if(ignore_path($Path));
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040019584 next if(skipLib($Path, $LibVersion));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019585 if(get_filename($Path)!~/\./
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019586 and cmd_file($Path)=~/(shared|dynamic)\s+library/i)
19587 {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019588 registerObject($Path, $LibVersion);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019589 $Libs{realpath($Path)}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019590 }
19591 }
19592 }
19593 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019594 return keys(%Libs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019595 }
19596 else {
19597 return ();
19598 }
19599}
19600
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019601sub isCyclical($$)
19602{
19603 my ($Stack, $Value) = @_;
19604 return (grep {$_ eq $Value} @{$Stack});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019605}
19606
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019607sub detectWordSize()
19608{
19609 return "" if(not $GCC_PATH);
19610 if($Cache{"detectWordSize"}) {
19611 return $Cache{"detectWordSize"};
19612 }
19613 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040019614 my $Defines = `$GCC_PATH -E -dD \"$TMP_DIR/empty.h\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019615 unlink("$TMP_DIR/empty.h");
19616 my $WSize = 0;
19617 if($Defines=~/ __SIZEOF_POINTER__\s+(\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019618 { # GCC 4
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019619 $WSize = $1;
19620 }
19621 elsif($Defines=~/ __PTRDIFF_TYPE__\s+(\w+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019622 { # GCC 3
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019623 my $PTRDIFF = $1;
19624 if($PTRDIFF=~/long/) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019625 $WSize = "8";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019626 }
19627 else {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019628 $WSize = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019629 }
19630 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019631 if(not $WSize) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019632 exitStatus("Error", "can't check WORD size");
19633 }
19634 return ($Cache{"detectWordSize"} = $WSize);
19635}
19636
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019637sub getWordSize($) {
19638 return $WORD_SIZE{$_[0]};
19639}
19640
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019641sub majorVersion($)
19642{
19643 my $V = $_[0];
19644 return 0 if(not $V);
19645 my @VParts = split(/\./, $V);
19646 return $VParts[0];
19647}
19648
19649sub cmpVersions($$)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019650{ # compare two versions in dotted-numeric format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019651 my ($V1, $V2) = @_;
19652 return 0 if($V1 eq $V2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019653 my @V1Parts = split(/\./, $V1);
19654 my @V2Parts = split(/\./, $V2);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019655 for (my $i = 0; $i <= $#V1Parts && $i <= $#V2Parts; $i++)
19656 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019657 return -1 if(int($V1Parts[$i]) < int($V2Parts[$i]));
19658 return 1 if(int($V1Parts[$i]) > int($V2Parts[$i]));
19659 }
19660 return -1 if($#V1Parts < $#V2Parts);
19661 return 1 if($#V1Parts > $#V2Parts);
19662 return 0;
19663}
19664
19665sub read_ABI_Dump($$)
19666{
19667 my ($LibVersion, $Path) = @_;
19668 return if(not $LibVersion or not -e $Path);
19669 my $FilePath = "";
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019670 if(isDump_U($Path))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019671 { # input *.abi
19672 $FilePath = $Path;
19673 }
19674 else
19675 { # input *.abi.tar.gz
19676 $FilePath = unpackDump($Path);
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019677 if(not isDump_U($FilePath)) {
19678 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19679 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019680 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019681
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019682 my $ABI = {};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019683
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019684 my $Line = readLineNum($FilePath, 0);
19685 if($Line=~/xml/)
19686 { # XML format
19687 loadModule("XmlDump");
19688 $ABI = readXmlDump($FilePath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019689 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019690 else
19691 { # Perl Data::Dumper format (default)
19692 open(DUMP, $FilePath);
19693 local $/ = undef;
19694 my $Content = <DUMP>;
19695 close(DUMP);
19696
19697 if(get_dirname($FilePath) eq $TMP_DIR."/unpack")
19698 { # remove temp file
19699 unlink($FilePath);
19700 }
19701 if($Content!~/};\s*\Z/) {
19702 exitStatus("Invalid_Dump", "specified ABI dump \'$Path\' is not valid, try to recreate it");
19703 }
19704 $ABI = eval($Content);
19705 if(not $ABI) {
19706 exitStatus("Error", "internal error - eval() procedure seem to not working correctly, try to remove 'use strict' and try again");
19707 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019708 }
19709 # new dumps (>=1.22) have a personal versioning
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019710 my $DVersion = $ABI->{"ABI_DUMP_VERSION"};
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019711 my $ToolVersion = $ABI->{"ABI_COMPLIANCE_CHECKER_VERSION"};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019712 if(not $DVersion)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019713 { # old dumps (<=1.21.6) have been marked by the tool version
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019714 $DVersion = $ToolVersion;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019715 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019716 $UsedDump{$LibVersion}{"V"} = $DVersion;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019717
19718 if($ABI->{"ABI_DUMP_VERSION"})
19719 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019720 if(cmpVersions($DVersion, $ABI_DUMP_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019721 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019722 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $ABI_DUMP_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019723 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019724 }
19725 else
19726 { # support for old ABI dumps
19727 if(cmpVersions($DVersion, $TOOL_VERSION)>0)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019728 { # Don't know how to parse future dump formats
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019729 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (newer than $TOOL_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019730 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019731 }
19732 if(majorVersion($DVersion)<2)
19733 { # support for old ABI dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019734 if($UseOldDumps)
19735 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019736 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)<0) {
19737 exitStatus("Dump_Version", "incompatible version \'$DVersion\' of specified ABI dump (older than $OLDEST_SUPPORTED_VERSION)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019738 }
19739 }
19740 else
19741 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019742 my $Msg = "incompatible version \'$DVersion\' of specified ABI dump (allowed only 2.0<=V<=$ABI_DUMP_VERSION)";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040019743 if(cmpVersions($DVersion, $OLDEST_SUPPORTED_VERSION)>=0) {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019744 $Msg .= "\nUse -old-dumps option to use old-version dumps ($OLDEST_SUPPORTED_VERSION<=V<2.0)";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019745 }
19746 exitStatus("Dump_Version", $Msg);
19747 }
19748 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019749
19750 if(defined $ABI->{"ABI_DUMPER_VERSION"})
19751 { # DWARF ABI Dump
19752 $UseConv_Real{$LibVersion}{"P"} = 1;
19753 $UseConv_Real{$LibVersion}{"R"} = 0; # not implemented yet
19754
19755 $UsedDump{$LibVersion}{"DWARF"} = 1;
19756
19757 $TargetComponent = "module";
19758 }
19759
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019760 if(not checkDump($LibVersion, "2.11"))
19761 { # old ABI dumps
19762 $UsedDump{$LibVersion}{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019763 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019764 elsif($ABI->{"BinOnly"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019765 { # ABI dump created with --binary option
19766 $UsedDump{$LibVersion}{"BinOnly"} = 1;
19767 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019768 else
19769 { # default
19770 $UsedDump{$LibVersion}{"SrcBin"} = 1;
19771 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019772
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019773 if(defined $ABI->{"Mode"}
19774 and $ABI->{"Mode"} eq "Extended")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019775 { # --ext option
19776 $ExtendedCheck = 1;
19777 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040019778 if($ABI->{"Extra"}) {
19779 $ExtraDump = 1;
19780 }
19781
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019782 if(my $Lang = $ABI->{"Language"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019783 {
19784 $UsedDump{$LibVersion}{"L"} = $Lang;
19785 setLanguage($LibVersion, $Lang);
19786 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019787 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019788 $TypeInfo{$LibVersion} = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019789 }
19790 else
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019791 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019792 my $TInfo = $ABI->{"TypeInfo"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019793 if(not $TInfo)
19794 { # support for older ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019795 $TInfo = $ABI->{"TypeDescr"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019796 }
19797 my %Tid_TDid = ();
19798 foreach my $TDid (keys(%{$TInfo}))
19799 {
19800 foreach my $Tid (keys(%{$TInfo->{$TDid}}))
19801 {
19802 $MAX_ID = $Tid if($Tid>$MAX_ID);
19803 $MAX_ID = $TDid if($TDid and $TDid>$MAX_ID);
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019804 $Tid_TDid{$Tid}{$TDid} = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019805 }
19806 }
19807 my %NewID = ();
19808 foreach my $Tid (keys(%Tid_TDid))
19809 {
19810 my @TDids = keys(%{$Tid_TDid{$Tid}});
19811 if($#TDids>=1)
19812 {
19813 foreach my $TDid (@TDids)
19814 {
19815 if($TDid) {
19816 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19817 }
19818 else
19819 {
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019820 my $ID = ++$MAX_ID;
19821
19822 $NewID{$TDid}{$Tid} = $ID;
19823 %{$TypeInfo{$LibVersion}{$ID}} = %{$TInfo->{$TDid}{$Tid}};
19824 $TypeInfo{$LibVersion}{$ID}{"Tid"} = $ID;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019825 }
19826 }
19827 }
19828 else
19829 {
19830 my $TDid = $TDids[0];
19831 %{$TypeInfo{$LibVersion}{$Tid}} = %{$TInfo->{$TDid}{$Tid}};
19832 }
19833 }
19834 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
19835 {
19836 my %Info = %{$TypeInfo{$LibVersion}{$Tid}};
19837 if(defined $Info{"BaseType"})
19838 {
19839 my $Bid = $Info{"BaseType"}{"Tid"};
19840 my $BDid = $Info{"BaseType"}{"TDid"};
19841 $BDid="" if(not defined $BDid);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019842 delete($TypeInfo{$LibVersion}{$Tid}{"BaseType"}{"TDid"});
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019843 if(defined $NewID{$BDid} and my $ID = $NewID{$BDid}{$Bid}) {
19844 $TypeInfo{$LibVersion}{$Tid}{"BaseType"} = $ID;
19845 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019846 }
19847 delete($TypeInfo{$LibVersion}{$Tid}{"TDid"});
19848 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019849 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019850 read_Machine_DumpInfo($ABI, $LibVersion);
19851 $SymbolInfo{$LibVersion} = $ABI->{"SymbolInfo"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019852 if(not $SymbolInfo{$LibVersion})
19853 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019854 $SymbolInfo{$LibVersion} = $ABI->{"FuncDescr"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019855 }
19856 if(not keys(%{$SymbolInfo{$LibVersion}}))
19857 { # validation of old-version dumps
19858 if(not $ExtendedCheck) {
19859 exitStatus("Invalid_Dump", "the input dump d$LibVersion is invalid");
19860 }
19861 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019862 if(checkDump($LibVersion, "2.15")) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019863 $DepLibrary_Symbol{$LibVersion} = $ABI->{"DepSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019864 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019865 else
19866 { # support for old ABI dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019867 my $DepSymbols = $ABI->{"DepSymbols"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019868 if(not $DepSymbols) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019869 $DepSymbols = $ABI->{"DepInterfaces"};
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019870 }
19871 if(not $DepSymbols)
19872 { # Cannot reconstruct DepSymbols. This may result in false
19873 # positives if the old dump is for library 2. Not a problem if
19874 # old dumps are only from old libraries.
19875 $DepSymbols = {};
19876 }
19877 foreach my $Symbol (keys(%{$DepSymbols})) {
19878 $DepSymbol_Library{$LibVersion}{$Symbol} = 1;
19879 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019880 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019881 $SymVer{$LibVersion} = $ABI->{"SymbolVersion"};
19882 $Descriptor{$LibVersion}{"Version"} = $ABI->{"LibraryVersion"};
19883 $SkipTypes{$LibVersion} = $ABI->{"SkipTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019884 if(not $SkipTypes{$LibVersion})
19885 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019886 $SkipTypes{$LibVersion} = $ABI->{"OpaqueTypes"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019887 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019888 $SkipSymbols{$LibVersion} = $ABI->{"SkipSymbols"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019889 if(not $SkipSymbols{$LibVersion})
19890 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019891 $SkipSymbols{$LibVersion} = $ABI->{"SkipInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019892 }
19893 if(not $SkipSymbols{$LibVersion})
19894 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019895 $SkipSymbols{$LibVersion} = $ABI->{"InternalInterfaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019896 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019897 $SkipNameSpaces{$LibVersion} = $ABI->{"SkipNameSpaces"};
19898 $TargetHeaders{$LibVersion} = $ABI->{"TargetHeaders"};
19899 foreach my $Path (keys(%{$ABI->{"SkipHeaders"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019900 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019901 $SkipHeadersList{$LibVersion}{$Path} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019902 my ($CPath, $Type) = classifyPath($Path);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019903 $SkipHeaders{$LibVersion}{$Type}{$CPath} = $ABI->{"SkipHeaders"}{$Path};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019904 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019905 read_Source_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019906 read_Libs_DumpInfo($ABI, $LibVersion);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040019907 if(not checkDump($LibVersion, "2.10.1")
19908 or not $TargetHeaders{$LibVersion})
Andrey Ponomarenko85043792012-05-14 16:48:07 +040019909 { # support for old ABI dumps: added target headers
19910 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040019911 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019912 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019913 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040019914 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019915 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019916 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019917 $Constants{$LibVersion} = $ABI->{"Constants"};
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019918 if(defined $ABI->{"GccConstants"})
19919 { # 3.0
19920 foreach my $Name (keys(%{$ABI->{"GccConstants"}})) {
19921 $Constants{$LibVersion}{$Name}{"Value"} = $ABI->{"GccConstants"}{$Name};
19922 }
19923 }
19924
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019925 $NestedNameSpaces{$LibVersion} = $ABI->{"NameSpaces"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019926 if(not $NestedNameSpaces{$LibVersion})
19927 { # support for old dumps
19928 # Cannot reconstruct NameSpaces. This may affect design
19929 # of the compatibility report.
19930 $NestedNameSpaces{$LibVersion} = {};
19931 }
19932 # target system type
19933 # needed to adopt HTML report
19934 if(not $DumpSystem)
19935 { # to use in createSymbolsList(...)
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040019936 $OStarget = $ABI->{"Target"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019937 }
19938 # recreate environment
19939 foreach my $Lib_Name (keys(%{$Library_Symbol{$LibVersion}}))
19940 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019941 foreach my $Symbol (keys(%{$Library_Symbol{$LibVersion}{$Lib_Name}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019942 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019943 $Symbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19944 if($Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol}<=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019945 { # data marked as -size in the dump
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019946 $GlobalDataObject{$LibVersion}{$Symbol} = -$Library_Symbol{$LibVersion}{$Lib_Name}{$Symbol};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019947 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040019948 if($COMMON_LANGUAGE{$LibVersion} ne "C++")
19949 {
19950 if(index($Symbol, "_Z")==0 or index($Symbol, "?")==0) {
19951 setLanguage($LibVersion, "C++");
19952 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019953 }
19954 }
19955 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019956 foreach my $Lib_Name (keys(%{$DepLibrary_Symbol{$LibVersion}}))
19957 {
19958 foreach my $Symbol (keys(%{$DepLibrary_Symbol{$LibVersion}{$Lib_Name}})) {
19959 $DepSymbol_Library{$LibVersion}{$Symbol} = $Lib_Name;
19960 }
19961 }
19962
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019963 my @VFunc = ();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040019964 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019965 {
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040019966 if(my $MnglName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019967 {
19968 if(not $Symbol_Library{$LibVersion}{$MnglName}
19969 and not $DepSymbol_Library{$LibVersion}{$MnglName}) {
19970 push(@VFunc, $MnglName);
19971 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040019972 }
19973 }
19974 translateSymbols(@VFunc, $LibVersion);
19975 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040019976 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
19977
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040019978 if(not checkDump($LibVersion, "3.0"))
19979 { # support for old ABI dumps
19980 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
19981 {
19982 if(my $BaseType = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
19983 {
19984 if(ref($BaseType) eq "HASH") {
19985 $TypeInfo{$LibVersion}{$TypeId}{"BaseType"} = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"}{"Tid"};
19986 }
19987 }
19988 }
19989 }
19990
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040019991 if(not checkDump($LibVersion, "3.2"))
19992 { # support for old ABI dumps
19993 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
19994 {
19995 if(defined $TypeInfo{$LibVersion}{$TypeId}{"VTable"})
19996 {
19997 foreach my $Offset (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"VTable"}})) {
19998 $TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset} = simplifyVTable($TypeInfo{$LibVersion}{$TypeId}{"VTable"}{$Offset});
19999 }
20000 }
20001 }
20002
20003 # repair target headers list
20004 delete($TargetHeaders{$LibVersion});
20005 foreach (keys(%{$Registered_Headers{$LibVersion}})) {
Andrey Ponomarenko3e69aa32013-06-26 15:38:07 +040020006 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
20007 }
20008 foreach (keys(%{$Registered_Sources{$LibVersion}})) {
20009 $TargetHeaders{$LibVersion}{get_filename($_)} = 1;
Andrey Ponomarenko177a66f2013-06-24 19:22:52 +040020010 }
20011
20012 # non-target constants from anon enums
20013 foreach my $Name (keys(%{$Constants{$LibVersion}}))
20014 {
20015 if(not $ExtraDump
20016 and not is_target_header($Constants{$LibVersion}{$Name}{"Header"}, $LibVersion))
20017 {
20018 delete($Constants{$LibVersion}{$Name});
20019 }
20020 }
20021 }
20022
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020023 if(not checkDump($LibVersion, "2.20"))
20024 { # support for old ABI dumps
20025 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20026 {
20027 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20028
20029 if($TType=~/Struct|Union|Enum|Typedef/)
20030 { # repair complex types first
20031 next;
20032 }
20033
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020034 if(my $BaseId = $TypeInfo{$LibVersion}{$TypeId}{"BaseType"})
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020035 {
20036 my $BType = lc($TypeInfo{$LibVersion}{$BaseId}{"Type"});
20037 if($BType=~/Struct|Union|Enum/i)
20038 {
20039 my $BName = $TypeInfo{$LibVersion}{$BaseId}{"Name"};
20040 $TypeInfo{$LibVersion}{$TypeId}{"Name"}=~s/\A\Q$BName\E\b/$BType $BName/g;
20041 }
20042 }
20043 }
20044 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
20045 {
20046 my $TType = $TypeInfo{$LibVersion}{$TypeId}{"Type"};
20047 my $TName = $TypeInfo{$LibVersion}{$TypeId}{"Name"};
20048 if($TType=~/Struct|Union|Enum/) {
20049 $TypeInfo{$LibVersion}{$TypeId}{"Name"} = lc($TType)." ".$TName;
20050 }
20051 }
20052 }
20053
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020054 foreach my $TypeId (sort {int($a)<=>int($b)} keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020055 { # order is important
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020056 if(defined $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"})
20057 { # support for old ABI dumps < 2.0 (ACC 1.22)
20058 foreach my $BId (keys(%{$TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}}))
20059 {
20060 if(my $Access = $TypeInfo{$LibVersion}{$TypeId}{"BaseClass"}{$BId})
20061 {
20062 if($Access ne "public") {
20063 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId}{"access"} = $Access;
20064 }
20065 }
20066 $TypeInfo{$LibVersion}{$TypeId}{"Base"}{$BId} = {};
20067 }
20068 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseClass"});
20069 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020070 if(my $Header = $TypeInfo{$LibVersion}{$TypeId}{"Header"})
20071 { # support for old ABI dumps
20072 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = path_format($Header, $OSgroup);
20073 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020074 elsif(my $Source = $TypeInfo{$LibVersion}{$TypeId}{"Source"})
20075 { # DWARF ABI Dumps
20076 $TypeInfo{$LibVersion}{$TypeId}{"Header"} = $Source;
20077 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020078 if(not defined $TypeInfo{$LibVersion}{$TypeId}{"Tid"}) {
20079 $TypeInfo{$LibVersion}{$TypeId}{"Tid"} = $TypeId;
20080 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020081 my %TInfo = %{$TypeInfo{$LibVersion}{$TypeId}};
20082 if(defined $TInfo{"Base"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020083 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020084 foreach (keys(%{$TInfo{"Base"}})) {
20085 $Class_SubClasses{$LibVersion}{$_}{$TypeId}=1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020086 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020087 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020088 if($TInfo{"Type"} eq "MethodPtr")
20089 {
20090 if(defined $TInfo{"Param"})
20091 { # support for old ABI dumps <= 1.17
20092 if(not defined $TInfo{"Param"}{"0"})
20093 {
20094 my $Max = keys(%{$TInfo{"Param"}});
20095 foreach my $Pos (1 .. $Max) {
20096 $TInfo{"Param"}{$Pos-1} = $TInfo{"Param"}{$Pos};
20097 }
20098 delete($TInfo{"Param"}{$Max});
20099 %{$TypeInfo{$LibVersion}{$TypeId}} = %TInfo;
20100 }
20101 }
20102 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020103 if($TInfo{"BaseType"} eq $TypeId)
20104 { # fix ABI dump
20105 delete($TypeInfo{$LibVersion}{$TypeId}{"BaseType"});
20106 }
20107 if($TInfo{"Type"} eq "Typedef" and not $TInfo{"Artificial"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020108 {
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020109 if(my $BTid = $TInfo{"BaseType"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020110 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020111 my $BName = $TypeInfo{$LibVersion}{$BTid}{"Name"};
20112 if(not $BName)
20113 { # broken type
20114 next;
20115 }
20116 if($TInfo{"Name"} eq $BName)
20117 { # typedef to "class Class"
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020118 # should not be registered in TName_Tid
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020119 next;
20120 }
20121 if(not $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}}) {
20122 $Typedef_BaseName{$LibVersion}{$TInfo{"Name"}} = $BName;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020123 }
20124 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020125 }
20126 if(not $TName_Tid{$LibVersion}{$TInfo{"Name"}})
20127 { # classes: class (id1), typedef (artificial, id2 > id1)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020128 $TName_Tid{$LibVersion}{formatName($TInfo{"Name"}, "T")} = $TypeId;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020129 }
20130 }
20131
20132 if(not checkDump($LibVersion, "2.15"))
20133 { # support for old ABI dumps
20134 my %Dups = ();
20135 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20136 {
20137 if(my $ClassId = $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020138 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020139 if(not defined $TypeInfo{$LibVersion}{$ClassId})
20140 { # remove template decls
20141 delete($SymbolInfo{$LibVersion}{$InfoId});
20142 next;
Andrey Ponomarenko16934472012-03-29 15:37:04 +040020143 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020144 }
Andrey Ponomarenkob8d203d2012-05-25 18:11:07 +040020145 my $MName = $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"};
20146 if(not $MName and $SymbolInfo{$LibVersion}{$InfoId}{"Class"})
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020147 { # templates
20148 delete($SymbolInfo{$LibVersion}{$InfoId});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020149 }
20150 }
20151 }
20152
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020153 foreach my $InfoId (keys(%{$SymbolInfo{$LibVersion}}))
20154 {
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040020155 if(my $Class = $SymbolInfo{$LibVersion}{$InfoId}{"Class"}
20156 and not $SymbolInfo{$LibVersion}{$InfoId}{"Static"}
20157 and not $SymbolInfo{$LibVersion}{$InfoId}{"Data"})
20158 { # support for old ABI dumps (< 3.1)
20159 if(not defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"}
20160 or $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{0}{"name"} ne "this")
20161 { # add "this" first parameter
20162 my $ThisTid = getTypeIdByName($TypeInfo{$LibVersion}{$Class}{"Name"}."*const", $LibVersion);
20163 my %PInfo = ("name"=>"this", "type"=>"$ThisTid");
20164
20165 if(defined $SymbolInfo{$LibVersion}{$InfoId}{"Param"})
20166 {
20167 my @Pos = sort {int($a)<=>int($b)} keys(%{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}});
20168 foreach my $Pos (reverse(0 .. $#Pos)) {
20169 %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos+1}} = %{$SymbolInfo{$LibVersion}{$InfoId}{"Param"}{$Pos}};
20170 }
20171 }
20172 $SymbolInfo{$LibVersion}{$InfoId}{"Param"}{"0"} = \%PInfo;
20173 }
20174 }
20175
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020176 if(not $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"})
20177 { # ABI dumps have no mangled names for C-functions
20178 $SymbolInfo{$LibVersion}{$InfoId}{"MnglName"} = $SymbolInfo{$LibVersion}{$InfoId}{"ShortName"};
20179 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020180 if(my $Header = $SymbolInfo{$LibVersion}{$InfoId}{"Header"})
20181 { # support for old ABI dumps
20182 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = path_format($Header, $OSgroup);
20183 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020184 elsif(my $Source = $SymbolInfo{$LibVersion}{$InfoId}{"Source"})
20185 { # DWARF ABI Dumps
20186 $SymbolInfo{$LibVersion}{$InfoId}{"Header"} = $Source;
20187 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040020188 }
20189
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020190 $Descriptor{$LibVersion}{"Dump"} = 1;
20191}
20192
20193sub read_Machine_DumpInfo($$)
20194{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020195 my ($ABI, $LibVersion) = @_;
20196 if($ABI->{"Arch"}) {
20197 $CPU_ARCH{$LibVersion} = $ABI->{"Arch"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020198 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020199 if($ABI->{"WordSize"}) {
20200 $WORD_SIZE{$LibVersion} = $ABI->{"WordSize"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020201 }
20202 else
20203 { # support for old dumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020204 $WORD_SIZE{$LibVersion} = $ABI->{"SizeOfPointer"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020205 }
20206 if(not $WORD_SIZE{$LibVersion})
20207 { # support for old dumps (<1.23)
20208 if(my $Tid = getTypeIdByName("char*", $LibVersion))
20209 { # size of char*
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020210 $WORD_SIZE{$LibVersion} = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020211 }
20212 else
20213 {
20214 my $PSize = 0;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020215 foreach my $Tid (keys(%{$TypeInfo{$LibVersion}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020216 {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020217 if($TypeInfo{$LibVersion}{$Tid}{"Type"} eq "Pointer")
20218 { # any "pointer"-type
20219 $PSize = $TypeInfo{$LibVersion}{$Tid}{"Size"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020220 last;
20221 }
20222 }
20223 if($PSize)
20224 { # a pointer type size
20225 $WORD_SIZE{$LibVersion} = $PSize;
20226 }
20227 else {
20228 printMsg("WARNING", "cannot identify a WORD size in the ABI dump (too old format)");
20229 }
20230 }
20231 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020232 if($ABI->{"GccVersion"}) {
20233 $GCC_VERSION{$LibVersion} = $ABI->{"GccVersion"};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020234 }
20235}
20236
20237sub read_Libs_DumpInfo($$)
20238{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020239 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020240 $Library_Symbol{$LibVersion} = $ABI->{"Symbols"};
20241 if(not $Library_Symbol{$LibVersion})
20242 { # support for old dumps
20243 $Library_Symbol{$LibVersion} = $ABI->{"Interfaces"};
20244 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020245 if(keys(%{$Library_Symbol{$LibVersion}})
20246 and not $DumpAPI) {
20247 $Descriptor{$LibVersion}{"Libs"} = "OK";
20248 }
20249}
20250
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020251sub read_Source_DumpInfo($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020252{
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020253 my ($ABI, $LibVersion) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020254
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020255 if(keys(%{$ABI->{"Headers"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020256 and not $DumpAPI) {
20257 $Descriptor{$LibVersion}{"Headers"} = "OK";
20258 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020259 foreach my $Identity (sort {$ABI->{"Headers"}{$a}<=>$ABI->{"Headers"}{$b}} keys(%{$ABI->{"Headers"}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020260 { # headers info is stored in the old dumps in the different way
20261 if($UseOldDumps
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020262 and my $Name = $ABI->{"Headers"}{$Identity}{"Name"})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020263 { # support for old dumps: headers info corrected in 1.22
20264 $Identity = $Name;
20265 }
20266 $Registered_Headers{$LibVersion}{$Identity}{"Identity"} = $Identity;
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020267 $Registered_Headers{$LibVersion}{$Identity}{"Pos"} = $ABI->{"Headers"}{$Identity};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020268 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020269
20270 if(keys(%{$ABI->{"Sources"}})
20271 and not $DumpAPI) {
20272 $Descriptor{$LibVersion}{"Sources"} = "OK";
20273 }
20274 foreach my $Name (sort {$ABI->{"Sources"}{$a}<=>$ABI->{"Sources"}{$b}} keys(%{$ABI->{"Sources"}}))
20275 { # headers info is stored in the old dumps in the different way
20276 $Registered_Sources{$LibVersion}{$Name}{"Identity"} = $Name;
20277 $Registered_Sources{$LibVersion}{$Name}{"Pos"} = $ABI->{"Headers"}{$Name};
20278 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020279}
20280
20281sub find_libs($$$)
20282{
20283 my ($Path, $Type, $MaxDepth) = @_;
20284 # FIXME: correct the search pattern
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020285 return cmd_find($Path, $Type, '\.'.$LIB_EXT.'[0-9.]*\Z', $MaxDepth, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020286}
20287
20288sub createDescriptor($$)
20289{
20290 my ($LibVersion, $Path) = @_;
20291 if(not $LibVersion or not $Path
20292 or not -e $Path) {
20293 return "";
20294 }
20295 if(-d $Path)
20296 { # directory with headers files and shared objects
20297 return "
20298 <version>
20299 ".$TargetVersion{$LibVersion}."
20300 </version>
20301
20302 <headers>
20303 $Path
20304 </headers>
20305
20306 <libs>
20307 $Path
20308 </libs>";
20309 }
20310 else
20311 { # files
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020312 if($Path=~/\.(xml|desc)\Z/i)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020313 { # standard XML-descriptor
20314 return readFile($Path);
20315 }
20316 elsif(is_header($Path, 2, $LibVersion))
20317 { # header file
20318 return "
20319 <version>
20320 ".$TargetVersion{$LibVersion}."
20321 </version>
20322
20323 <headers>
20324 $Path
20325 </headers>
20326
20327 <libs>
20328 none
20329 </libs>";
20330 }
20331 elsif(parse_libname($Path, "name", $OStarget))
20332 { # shared object
20333 return "
20334 <version>
20335 ".$TargetVersion{$LibVersion}."
20336 </version>
20337
20338 <headers>
20339 none
20340 </headers>
20341
20342 <libs>
20343 $Path
20344 </libs>";
20345 }
20346 else
20347 { # standard XML-descriptor
20348 return readFile($Path);
20349 }
20350 }
20351}
20352
20353sub detect_lib_default_paths()
20354{
20355 my %LPaths = ();
20356 if($OSgroup eq "bsd")
20357 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020358 if(my $LdConfig = get_CmdPath("ldconfig"))
20359 {
20360 foreach my $Line (split(/\n/, `$LdConfig -r 2>\"$TMP_DIR/null\"`))
20361 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020362 if($Line=~/\A[ \t]*\d+:\-l(.+) \=\> (.+)\Z/)
20363 {
20364 my $Name = "lib".$1;
20365 if(not defined $LPaths{$Name}) {
20366 $LPaths{$Name} = $2;
20367 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020368 }
20369 }
20370 }
20371 else {
20372 printMsg("WARNING", "can't find ldconfig");
20373 }
20374 }
20375 else
20376 {
20377 if(my $LdConfig = get_CmdPath("ldconfig"))
20378 {
20379 if($SystemRoot and $OSgroup eq "linux")
20380 { # use host (x86) ldconfig with the target (arm) ld.so.conf
20381 if(-e $SystemRoot."/etc/ld.so.conf") {
20382 $LdConfig .= " -f ".$SystemRoot."/etc/ld.so.conf";
20383 }
20384 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020385 foreach my $Line (split(/\n/, `$LdConfig -p 2>\"$TMP_DIR/null\"`))
20386 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020387 if($Line=~/\A[ \t]*([^ \t]+) .* \=\> (.+)\Z/)
20388 {
20389 my ($Name, $Path) = ($1, $2);
20390 $Path=~s/[\/]{2,}/\//;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020391 if(not defined $LPaths{$Name})
20392 { # get first element from the list of available paths
20393
20394 # libstdc++.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
20395 # libstdc++.so.6 (libc6) => /usr/lib/i386-linux-gnu/libstdc++.so.6
20396 # libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
20397
20398 $LPaths{$Name} = $Path;
20399 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020400 }
20401 }
20402 }
Andrey Ponomarenko82b005f2012-11-12 17:58:14 +040020403 elsif($OSgroup eq "linux") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020404 printMsg("WARNING", "can't find ldconfig");
20405 }
20406 }
20407 return \%LPaths;
20408}
20409
20410sub detect_bin_default_paths()
20411{
20412 my $EnvPaths = $ENV{"PATH"};
20413 if($OSgroup eq "beos") {
20414 $EnvPaths.=":".$ENV{"BETOOLS"};
20415 }
20416 my $Sep = ($OSgroup eq "windows")?";":":|;";
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020417 foreach my $Path (split(/$Sep/, $EnvPaths))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020418 {
20419 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020420 next if(not $Path);
20421 if($SystemRoot
20422 and $Path=~/\A\Q$SystemRoot\E\//)
20423 { # do NOT use binaries from target system
20424 next;
20425 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020426 push_U(\@DefaultBinPaths, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020427 }
20428}
20429
20430sub detect_inc_default_paths()
20431{
20432 return () if(not $GCC_PATH);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020433 my %DPaths = ("Cpp"=>[],"Gcc"=>[],"Inc"=>[]);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020434 writeFile("$TMP_DIR/empty.h", "");
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020435 foreach my $Line (split(/\n/, `$GCC_PATH -v -x c++ -E \"$TMP_DIR/empty.h\" 2>&1`))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020436 { # detecting GCC default include paths
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020437 next if(index($Line, "/cc1plus ")!=-1);
20438
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020439 if($Line=~/\A[ \t]*((\/|\w+:\\).+)[ \t]*\Z/)
20440 {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020441 my $Path = realpath($1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020442 $Path = path_format($Path, $OSgroup);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020443 if(index($Path, "c++")!=-1
20444 or index($Path, "/g++/")!=-1)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020445 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020446 push_U($DPaths{"Cpp"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020447 if(not defined $MAIN_CPP_DIR
20448 or get_depth($MAIN_CPP_DIR)>get_depth($Path)) {
20449 $MAIN_CPP_DIR = $Path;
20450 }
20451 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020452 elsif(index($Path, "gcc")!=-1) {
20453 push_U($DPaths{"Gcc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020454 }
20455 else
20456 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020457 if($Path=~/local[\/\\]+include/)
20458 { # local paths
20459 next;
20460 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020461 if($SystemRoot
20462 and $Path!~/\A\Q$SystemRoot\E(\/|\Z)/)
20463 { # The GCC include path for user headers is not a part of the system root
20464 # The reason: you are not specified the --cross-gcc option or selected a wrong compiler
20465 # or it is the internal cross-GCC path like arm-linux-gnueabi/include
20466 next;
20467 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020468 push_U($DPaths{"Inc"}, $Path);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020469 }
20470 }
20471 }
20472 unlink("$TMP_DIR/empty.h");
20473 return %DPaths;
20474}
20475
20476sub detect_default_paths($)
20477{
20478 my ($HSearch, $LSearch, $BSearch, $GSearch) = (1, 1, 1, 1);
20479 my $Search = $_[0];
20480 if($Search!~/inc/) {
20481 $HSearch = 0;
20482 }
20483 if($Search!~/lib/) {
20484 $LSearch = 0;
20485 }
20486 if($Search!~/bin/) {
20487 $BSearch = 0;
20488 }
20489 if($Search!~/gcc/) {
20490 $GSearch = 0;
20491 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020492 if(@{$SystemPaths{"include"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020493 { # <search_headers> section of the XML descriptor
20494 # do NOT search for systems headers
20495 $HSearch = 0;
20496 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020497 if(@{$SystemPaths{"lib"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020498 { # <search_headers> section of the XML descriptor
20499 # do NOT search for systems headers
20500 $LSearch = 0;
20501 }
20502 foreach my $Type (keys(%{$OS_AddPath{$OSgroup}}))
20503 { # additional search paths
20504 next if($Type eq "include" and not $HSearch);
20505 next if($Type eq "lib" and not $LSearch);
20506 next if($Type eq "bin" and not $BSearch);
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020507 push_U($SystemPaths{$Type}, grep { -d $_ } @{$OS_AddPath{$OSgroup}{$Type}});
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020508 }
20509 if($OSgroup ne "windows")
20510 { # unix-like
20511 foreach my $Type ("include", "lib", "bin")
20512 { # automatic detection of system "devel" directories
20513 next if($Type eq "include" and not $HSearch);
20514 next if($Type eq "lib" and not $LSearch);
20515 next if($Type eq "bin" and not $BSearch);
20516 my ($UsrDir, $RootDir) = ("/usr", "/");
20517 if($SystemRoot and $Type ne "bin")
20518 { # 1. search for target headers and libraries
20519 # 2. use host commands: ldconfig, readelf, etc.
20520 ($UsrDir, $RootDir) = ("$SystemRoot/usr", $SystemRoot);
20521 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020522 push_U($SystemPaths{$Type}, cmd_find($RootDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020523 if(-d $RootDir."/".$Type)
20524 { # if "/lib" is symbolic link
20525 if($RootDir eq "/") {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020526 push_U($SystemPaths{$Type}, "/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020527 }
20528 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020529 push_U($SystemPaths{$Type}, $RootDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020530 }
20531 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020532 if(-d $UsrDir)
20533 {
20534 push_U($SystemPaths{$Type}, cmd_find($UsrDir,"d","*$Type*",1));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020535 if(-d $UsrDir."/".$Type)
20536 { # if "/usr/lib" is symbolic link
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020537 push_U($SystemPaths{$Type}, $UsrDir."/".$Type);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020538 }
20539 }
20540 }
20541 }
20542 if($BSearch)
20543 {
20544 detect_bin_default_paths();
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020545 push_U($SystemPaths{"bin"}, @DefaultBinPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020546 }
20547 # check environment variables
20548 if($OSgroup eq "beos")
20549 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020550 foreach (my @Paths = @{$SystemPaths{"bin"}})
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020551 {
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040020552 if($_ eq ".") {
20553 next;
20554 }
20555 # search for /boot/develop/abi/x86/gcc4/tools/gcc-4.4.4-haiku-101111/bin/
20556 if(my @Dirs = sort cmd_find($_, "d", "bin")) {
20557 push_U($SystemPaths{"bin"}, sort {get_depth($a)<=>get_depth($b)} @Dirs);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020558 }
20559 }
20560 if($HSearch)
20561 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020562 push_U(\@DefaultIncPaths, grep { is_abs($_) } (
20563 split(/:|;/, $ENV{"BEINCLUDES"})
20564 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020565 }
20566 if($LSearch)
20567 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020568 push_U(\@DefaultLibPaths, grep { is_abs($_) } (
20569 split(/:|;/, $ENV{"BELIBRARIES"}),
20570 split(/:|;/, $ENV{"LIBRARY_PATH"})
20571 ));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020572 }
20573 }
20574 if($LSearch)
20575 { # using linker to get system paths
20576 if(my $LPaths = detect_lib_default_paths())
20577 { # unix-like
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020578 my %Dirs = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020579 foreach my $Name (keys(%{$LPaths}))
20580 {
20581 if($SystemRoot
20582 and $LPaths->{$Name}!~/\A\Q$SystemRoot\E\//)
20583 { # wrong ldconfig configuration
20584 # check your <sysroot>/etc/ld.so.conf
20585 next;
20586 }
20587 $DyLib_DefaultPath{$Name} = $LPaths->{$Name};
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020588 if(my $Dir = get_dirname($LPaths->{$Name})) {
20589 $Dirs{$Dir} = 1;
20590 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020591 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020592 push_U(\@DefaultLibPaths, sort {get_depth($a)<=>get_depth($b)} sort keys(%Dirs));
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020593 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020594 push_U($SystemPaths{"lib"}, @DefaultLibPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020595 }
20596 if($BSearch)
20597 {
20598 if($CrossGcc)
20599 { # --cross-gcc=arm-linux-gcc
20600 if(-e $CrossGcc)
20601 { # absolute or relative path
20602 $GCC_PATH = get_abs_path($CrossGcc);
20603 }
20604 elsif($CrossGcc!~/\// and get_CmdPath($CrossGcc))
20605 { # command name
20606 $GCC_PATH = $CrossGcc;
20607 }
20608 else {
20609 exitStatus("Access_Error", "can't access \'$CrossGcc\'");
20610 }
20611 if($GCC_PATH=~/\s/) {
20612 $GCC_PATH = "\"".$GCC_PATH."\"";
20613 }
20614 }
20615 }
20616 if($GSearch)
20617 { # GCC path and default include dirs
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020618 if(not $CrossGcc)
20619 { # try default gcc
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020620 $GCC_PATH = get_CmdPath("gcc");
20621 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020622 if(not $GCC_PATH)
20623 { # try to find gcc-X.Y
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020624 foreach my $Path (@{$SystemPaths{"bin"}})
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020625 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040020626 if(my @GCCs = cmd_find($Path, "", '/gcc-[0-9.]*\Z', 1, 1))
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040020627 { # select the latest version
20628 @GCCs = sort {$b cmp $a} @GCCs;
20629 if(check_gcc($GCCs[0], "3"))
20630 {
20631 $GCC_PATH = $GCCs[0];
20632 last;
20633 }
20634 }
20635 }
20636 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020637 if(not $GCC_PATH) {
20638 exitStatus("Not_Found", "can't find GCC>=3.0 in PATH");
20639 }
20640 if(not $CheckObjectsOnly_Opt)
20641 {
20642 if(my $GCC_Ver = get_dumpversion($GCC_PATH))
20643 {
20644 my $GccTarget = get_dumpmachine($GCC_PATH);
20645 printMsg("INFO", "Using GCC $GCC_Ver ($GccTarget)");
20646 if($GccTarget=~/symbian/)
20647 {
20648 $OStarget = "symbian";
20649 $LIB_EXT = $OS_LibExt{$LIB_TYPE}{$OStarget};
20650 }
20651 }
20652 else {
20653 exitStatus("Error", "something is going wrong with the GCC compiler");
20654 }
20655 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020656 if($HSearch)
20657 {
20658 if(not $NoStdInc)
20659 { # do NOT search in GCC standard paths
20660 my %DPaths = detect_inc_default_paths();
20661 @DefaultCppPaths = @{$DPaths{"Cpp"}};
20662 @DefaultGccPaths = @{$DPaths{"Gcc"}};
20663 @DefaultIncPaths = @{$DPaths{"Inc"}};
20664 push_U($SystemPaths{"include"}, @DefaultIncPaths);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020665 }
20666 }
20667 }
20668 if($HSearch)
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020669 { # users include paths
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020670 my $IncPath = "/usr/include";
20671 if($SystemRoot) {
20672 $IncPath = $SystemRoot.$IncPath;
20673 }
20674 if(-d $IncPath) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020675 push_U(\@UsersIncPath, $IncPath);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020676 }
20677 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020678
20679 if($ExtraInfo)
20680 {
20681 writeFile($ExtraInfo."/default-libs", join("\n", @DefaultLibPaths));
20682 writeFile($ExtraInfo."/default-includes", join("\n", (@DefaultCppPaths, @DefaultGccPaths, @DefaultIncPaths)));
20683 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020684}
20685
20686sub getLIB_EXT($)
20687{
20688 my $Target = $_[0];
20689 if(my $Ext = $OS_LibExt{$LIB_TYPE}{$Target}) {
20690 return $Ext;
20691 }
20692 return $OS_LibExt{$LIB_TYPE}{"default"};
20693}
20694
20695sub getAR_EXT($)
20696{
20697 my $Target = $_[0];
20698 if(my $Ext = $OS_Archive{$Target}) {
20699 return $Ext;
20700 }
20701 return $OS_Archive{"default"};
20702}
20703
20704sub get_dumpversion($)
20705{
20706 my $Cmd = $_[0];
20707 return "" if(not $Cmd);
20708 if($Cache{"get_dumpversion"}{$Cmd}) {
20709 return $Cache{"get_dumpversion"}{$Cmd};
20710 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020711 my $V = `$Cmd -dumpversion 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020712 chomp($V);
20713 return ($Cache{"get_dumpversion"}{$Cmd} = $V);
20714}
20715
20716sub get_dumpmachine($)
20717{
20718 my $Cmd = $_[0];
20719 return "" if(not $Cmd);
20720 if($Cache{"get_dumpmachine"}{$Cmd}) {
20721 return $Cache{"get_dumpmachine"}{$Cmd};
20722 }
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020723 my $Machine = `$Cmd -dumpmachine 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020724 chomp($Machine);
20725 return ($Cache{"get_dumpmachine"}{$Cmd} = $Machine);
20726}
20727
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020728sub checkCmd($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020729{
20730 my $Cmd = $_[0];
20731 return "" if(not $Cmd);
20732 my @Options = (
20733 "--version",
20734 "-help"
20735 );
20736 foreach my $Opt (@Options)
20737 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020738 my $Info = `$Cmd $Opt 2>\"$TMP_DIR/null\"`;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020739 if($Info) {
20740 return 1;
20741 }
20742 }
20743 return 0;
20744}
20745
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020746sub check_gcc($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020747{
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020748 my ($Cmd, $ReqVer) = @_;
20749 return 0 if(not $Cmd or not $ReqVer);
20750 if(defined $Cache{"check_gcc"}{$Cmd}{$ReqVer}) {
20751 return $Cache{"check_gcc"}{$Cmd}{$ReqVer};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020752 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040020753 if(my $GccVer = get_dumpversion($Cmd))
20754 {
20755 $GccVer=~s/(-|_)[a-z_]+.*\Z//; # remove suffix (like "-haiku-100818")
20756 if(cmpVersions($GccVer, $ReqVer)>=0) {
20757 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = $Cmd);
20758 }
20759 }
20760 return ($Cache{"check_gcc"}{$Cmd}{$ReqVer} = "");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020761}
20762
20763sub get_depth($)
20764{
20765 if(defined $Cache{"get_depth"}{$_[0]}) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020766 return $Cache{"get_depth"}{$_[0]};
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020767 }
20768 return ($Cache{"get_depth"}{$_[0]} = ($_[0]=~tr![\/\\]|\:\:!!));
20769}
20770
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020771sub registerGccHeaders()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020772{
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020773 return if($Cache{"registerGccHeaders"}); # this function should be called once
20774
20775 foreach my $Path (@DefaultGccPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020776 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020777 my @Headers = cmd_find($Path,"f");
20778 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20779 foreach my $HPath (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020780 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020781 my $FileName = get_filename($HPath);
20782 if(not defined $DefaultGccHeader{$FileName})
20783 { # skip duplicated
20784 $DefaultGccHeader{$FileName} = $HPath;
20785 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020786 }
20787 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020788 $Cache{"registerGccHeaders"} = 1;
20789}
20790
20791sub registerCppHeaders()
20792{
20793 return if($Cache{"registerCppHeaders"}); # this function should be called once
20794
20795 foreach my $CppDir (@DefaultCppPaths)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020796 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020797 my @Headers = cmd_find($CppDir,"f");
20798 @Headers = sort {get_depth($a)<=>get_depth($b)} @Headers;
20799 foreach my $Path (@Headers)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020800 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020801 my $FileName = get_filename($Path);
20802 if(not defined $DefaultCppHeader{$FileName})
20803 { # skip duplicated
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020804 $DefaultCppHeader{$FileName} = $Path;
20805 }
20806 }
20807 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040020808 $Cache{"registerCppHeaders"} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020809}
20810
20811sub parse_libname($$$)
20812{
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020813 return "" if(not $_[0]);
20814 if(defined $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]}) {
20815 return $Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]};
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040020816 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040020817 return ($Cache{"parse_libname"}{$_[2]}{$_[1]}{$_[0]} = parse_libname_I(@_));
20818}
20819
20820sub parse_libname_I($$$)
20821{
20822 my ($Name, $Type, $Target) = @_;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020823
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020824 if($Target eq "symbian") {
20825 return parse_libname_symbian($Name, $Type);
20826 }
20827 elsif($Target eq "windows") {
20828 return parse_libname_windows($Name, $Type);
20829 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040020830
20831 # unix
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020832 my $Ext = getLIB_EXT($Target);
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020833 if($Name=~/((((lib|).+?)([\-\_][\d\-\.\_]+.*?|))\.$Ext)(\.(.+)|)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020834 { # libSDL-1.2.so.0.7.1
20835 # libwbxml2.so.0.0.18
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020836 # libopcodes-2.21.53-system.20110810.so
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020837 if($Type eq "name")
20838 { # libSDL-1.2
20839 # libwbxml2
20840 return $2;
20841 }
20842 elsif($Type eq "name+ext")
20843 { # libSDL-1.2.so
20844 # libwbxml2.so
20845 return $1;
20846 }
20847 elsif($Type eq "version")
20848 {
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040020849 if(defined $7
20850 and $7 ne "")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020851 { # 0.7.1
20852 return $7;
20853 }
20854 else
20855 { # libc-2.5.so (=>2.5 version)
20856 my $MV = $5;
20857 $MV=~s/\A[\-\_]+//g;
20858 return $MV;
20859 }
20860 }
20861 elsif($Type eq "short")
20862 { # libSDL
20863 # libwbxml2
20864 return $3;
20865 }
20866 elsif($Type eq "shortest")
20867 { # SDL
20868 # wbxml
20869 return shortest_name($3);
20870 }
20871 }
20872 return "";# error
20873}
20874
20875sub parse_libname_symbian($$)
20876{
20877 my ($Name, $Type) = @_;
20878 my $Ext = getLIB_EXT("symbian");
20879 if($Name=~/(((.+?)(\{.+\}|))\.$Ext)\Z/)
20880 { # libpthread{00010001}.dso
20881 if($Type eq "name")
20882 { # libpthread{00010001}
20883 return $2;
20884 }
20885 elsif($Type eq "name+ext")
20886 { # libpthread{00010001}.dso
20887 return $1;
20888 }
20889 elsif($Type eq "version")
20890 { # 00010001
20891 my $V = $4;
20892 $V=~s/\{(.+)\}/$1/;
20893 return $V;
20894 }
20895 elsif($Type eq "short")
20896 { # libpthread
20897 return $3;
20898 }
20899 elsif($Type eq "shortest")
20900 { # pthread
20901 return shortest_name($3);
20902 }
20903 }
20904 return "";# error
20905}
20906
20907sub parse_libname_windows($$)
20908{
20909 my ($Name, $Type) = @_;
20910 my $Ext = getLIB_EXT("windows");
20911 if($Name=~/((.+?)\.$Ext)\Z/)
20912 { # netapi32.dll
20913 if($Type eq "name")
20914 { # netapi32
20915 return $2;
20916 }
20917 elsif($Type eq "name+ext")
20918 { # netapi32.dll
20919 return $1;
20920 }
20921 elsif($Type eq "version")
20922 { # DLL version embedded
20923 # at binary-level
20924 return "";
20925 }
20926 elsif($Type eq "short")
20927 { # netapi32
20928 return $2;
20929 }
20930 elsif($Type eq "shortest")
20931 { # netapi
20932 return shortest_name($2);
20933 }
20934 }
20935 return "";# error
20936}
20937
20938sub shortest_name($)
20939{
20940 my $Name = $_[0];
20941 # remove prefix
20942 $Name=~s/\A(lib|open)//;
20943 # remove suffix
20944 $Name=~s/[\W\d_]+\Z//i;
20945 $Name=~s/([a-z]{2,})(lib)\Z/$1/i;
20946 return $Name;
20947}
20948
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020949sub createSymbolsList($$$$$)
20950{
20951 my ($DPath, $SaveTo, $LName, $LVersion, $ArchName) = @_;
20952 read_ABI_Dump(1, $DPath);
20953 if(not $CheckObjectsOnly) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020954 prepareSymbols(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020955 }
20956 my %SymbolHeaderLib = ();
20957 my $Total = 0;
20958 # Get List
20959 foreach my $Symbol (sort keys(%{$CompleteSignature{1}}))
20960 {
20961 if(not link_symbol($Symbol, 1, "-Deps"))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020962 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020963 next;
20964 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020965 if(not symbolFilter($Symbol, 1, "Public", "Binary"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020966 { # skip other symbols
20967 next;
20968 }
20969 my $HeaderName = $CompleteSignature{1}{$Symbol}{"Header"};
20970 if(not $HeaderName)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020971 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020972 next;
20973 }
20974 my $DyLib = $Symbol_Library{1}{$Symbol};
20975 if(not $DyLib)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020976 { # skip src only and all external functions
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020977 next;
20978 }
20979 $SymbolHeaderLib{$HeaderName}{$DyLib}{$Symbol} = 1;
20980 $Total+=1;
20981 }
20982 # Draw List
20983 my $SYMBOLS_LIST = "<h1>Public symbols in <span style='color:Blue;'>$LName</span> (<span style='color:Red;'>$LVersion</span>)";
20984 $SYMBOLS_LIST .= " on <span style='color:Blue;'>".showArch($ArchName)."</span><br/>Total: $Total</h1><br/>";
20985 foreach my $HeaderName (sort {lc($a) cmp lc($b)} keys(%SymbolHeaderLib))
20986 {
20987 foreach my $DyLib (sort {lc($a) cmp lc($b)} keys(%{$SymbolHeaderLib{$HeaderName}}))
20988 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020989 my %NS_Symbol = ();
20990 foreach my $Symbol (keys(%{$SymbolHeaderLib{$HeaderName}{$DyLib}})) {
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040020991 $NS_Symbol{select_Symbol_NS($Symbol, 1)}{$Symbol} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020992 }
20993 foreach my $NameSpace (sort keys(%NS_Symbol))
20994 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040020995 $SYMBOLS_LIST .= getTitle($HeaderName, $DyLib, $NameSpace);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040020996 my @SortedInterfaces = sort {lc(get_Signature($a, 1)) cmp lc(get_Signature($b, 1))} keys(%{$NS_Symbol{$NameSpace}});
20997 foreach my $Symbol (@SortedInterfaces)
20998 {
20999 my $SubReport = "";
21000 my $Signature = get_Signature($Symbol, 1);
21001 if($NameSpace) {
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021002 $Signature=~s/\b\Q$NameSpace\E::\b//g;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021003 }
21004 if($Symbol=~/\A(_Z|\?)/)
21005 {
21006 if($Signature) {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021007 $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 +040021008 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021009 else {
21010 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21011 }
21012 }
21013 else
21014 {
21015 if($Signature) {
21016 $SubReport = "<span class='iname'>".highLight_Signature_Italic_Color($Signature)."</span><br/>\n";
21017 }
21018 else {
21019 $SubReport = "<span class='iname'>".$Symbol."</span><br/>\n";
21020 }
21021 }
21022 $SYMBOLS_LIST .= $SubReport;
21023 }
21024 }
21025 $SYMBOLS_LIST .= "<br/>\n";
21026 }
21027 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021028 # clear info
21029 (%TypeInfo, %SymbolInfo, %Library_Symbol, %DepSymbol_Library,
21030 %DepLibrary_Symbol, %SymVer, %SkipTypes, %SkipSymbols,
21031 %NestedNameSpaces, %ClassMethods, %AllocableClass, %ClassNames,
21032 %CompleteSignature, %SkipNameSpaces, %Symbol_Library, %Library_Symbol) = ();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021033 ($Content_Counter, $ContentID) = (0, 0);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021034 # print report
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021035 my $CssStyles = readModule("Styles", "SymbolsList.css");
21036 my $JScripts = readModule("Scripts", "Sections.js");
21037 $SYMBOLS_LIST = "<a name='Top'></a>".$SYMBOLS_LIST.$TOP_REF."<br/>\n";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021038 my $Title = "$LName: public symbols";
21039 my $Keywords = "$LName, API, symbols";
21040 my $Description = "List of symbols in $LName ($LVersion) on ".showArch($ArchName);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021041 $SYMBOLS_LIST = composeHTML_Head($Title, $Keywords, $Description, $CssStyles, $JScripts)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021042 <body><div>\n$SYMBOLS_LIST</div>
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021043 <br/><br/><hr/>\n".getReportFooter($LName, 1)."
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021044 <div style='height:999px;'></div></body></html>";
21045 writeFile($SaveTo, $SYMBOLS_LIST);
21046}
21047
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021048sub add_target_libs($)
21049{
21050 foreach (@{$_[0]}) {
21051 $TargetLibs{$_} = 1;
21052 }
21053}
21054
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021055sub is_target_lib($)
21056{
21057 my $LName = $_[0];
Andrey Ponomarenkoa01311b2012-06-08 17:20:02 +040021058 if(not $LName) {
21059 return 0;
21060 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021061 if($TargetLibraryName
21062 and $LName!~/\Q$TargetLibraryName\E/) {
21063 return 0;
21064 }
21065 if(keys(%TargetLibs)
21066 and not $TargetLibs{$LName}
21067 and not $TargetLibs{parse_libname($LName, "name+ext", $OStarget)}) {
21068 return 0;
21069 }
21070 return 1;
21071}
21072
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021073sub is_target_header($$)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021074{ # --header, --headers-list
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021075 my ($H, $V) = @_;
21076 if(keys(%{$TargetHeaders{$V}}))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021077 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021078 if($TargetHeaders{$V}{$H}) {
21079 return 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021080 }
21081 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021082 return 0;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021083}
21084
21085sub checkVersionNum($$)
21086{
21087 my ($LibVersion, $Path) = @_;
21088 if(my $VerNum = $TargetVersion{$LibVersion}) {
21089 return $VerNum;
21090 }
21091 my $UsedAltDescr = 0;
21092 foreach my $Part (split(/\s*,\s*/, $Path))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021093 { # try to get version string from file path
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021094 next if(isDump($Part)); # ABI dump
21095 next if($Part=~/\.(xml|desc)\Z/i); # XML descriptor
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021096 my $VerNum = "";
21097 if(parse_libname($Part, "name", $OStarget))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021098 {
21099 $UsedAltDescr = 1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021100 $VerNum = parse_libname($Part, "version", $OStarget);
21101 if(not $VerNum) {
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021102 $VerNum = readStrVer($Part);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021103 }
21104 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021105 elsif(is_header($Part, 2, $LibVersion) or -d $Part)
21106 {
21107 $UsedAltDescr = 1;
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021108 $VerNum = readStrVer($Part);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021109 }
21110 if($VerNum ne "")
21111 {
21112 $TargetVersion{$LibVersion} = $VerNum;
21113 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021114 printMsg("WARNING", "setting version number to $VerNum (use -vnum option to change it)");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021115 }
21116 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021117 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 +040021118 }
21119 return $TargetVersion{$LibVersion};
21120 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021121 }
21122 if($UsedAltDescr)
21123 {
21124 if($DumpAPI) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021125 exitStatus("Error", "version number is not set (use -vnum option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021126 }
21127 else {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021128 exitStatus("Error", ($LibVersion==1?"1st":"2nd")." version number is not set (use -v$LibVersion option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021129 }
21130 }
21131}
21132
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021133sub readStrVer($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021134{
21135 my $Str = $_[0];
21136 return "" if(not $Str);
21137 $Str=~s/\Q$TargetLibraryName\E//g;
21138 if($Str=~/(\/|\\|\w|\A)[\-\_]*(\d+[\d\.\-]+\d+|\d+)/)
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021139 { # .../libssh-0.4.0/...
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021140 return $2;
21141 }
21142 elsif(my $V = parse_libname($Str, "version", $OStarget)) {
21143 return $V;
21144 }
21145 return "";
21146}
21147
21148sub readLibs($)
21149{
21150 my $LibVersion = $_[0];
21151 if($OStarget eq "windows")
21152 { # dumpbin.exe will crash
21153 # without VS Environment
21154 check_win32_env();
21155 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040021156 readSymbols($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021157 translateSymbols(keys(%{$Symbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021158 translateSymbols(keys(%{$DepSymbol_Library{$LibVersion}}), $LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021159}
21160
21161sub dump_sorting($)
21162{
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021163 my $Hash = $_[0];
21164 return [] if(not $Hash);
21165 my @Keys = keys(%{$Hash});
21166 return [] if($#Keys<0);
21167 if($Keys[0]=~/\A\d+\Z/)
21168 { # numbers
21169 return [sort {int($a)<=>int($b)} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021170 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040021171 else
21172 { # strings
21173 return [sort {$a cmp $b} @Keys];
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021174 }
21175}
21176
21177sub printMsg($$)
21178{
21179 my ($Type, $Msg) = @_;
21180 if($Type!~/\AINFO/) {
21181 $Msg = $Type.": ".$Msg;
21182 }
21183 if($Type!~/_C\Z/) {
21184 $Msg .= "\n";
21185 }
21186 if($Quiet)
21187 { # --quiet option
21188 appendFile($COMMON_LOG_PATH, $Msg);
21189 }
21190 else
21191 {
21192 if($Type eq "ERROR") {
21193 print STDERR $Msg;
21194 }
21195 else {
21196 print $Msg;
21197 }
21198 }
21199}
21200
21201sub exitStatus($$)
21202{
21203 my ($Code, $Msg) = @_;
21204 printMsg("ERROR", $Msg);
21205 exit($ERROR_CODE{$Code});
21206}
21207
21208sub exitReport()
21209{ # the tool has run without any errors
21210 printReport();
21211 if($COMPILE_ERRORS)
21212 { # errors in headers may add false positives/negatives
21213 exit($ERROR_CODE{"Compile_Error"});
21214 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021215 if($BinaryOnly and $RESULT{"Binary"}{"Problems"})
21216 { # --binary
21217 exit($ERROR_CODE{"Incompatible"});
21218 }
21219 elsif($SourceOnly and $RESULT{"Source"}{"Problems"})
21220 { # --source
21221 exit($ERROR_CODE{"Incompatible"});
21222 }
21223 elsif($RESULT{"Source"}{"Problems"}
21224 or $RESULT{"Binary"}{"Problems"})
21225 { # default
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021226 exit($ERROR_CODE{"Incompatible"});
21227 }
21228 else {
21229 exit($ERROR_CODE{"Compatible"});
21230 }
21231}
21232
21233sub readRules($)
21234{
21235 my $Kind = $_[0];
21236 if(not -f $RULES_PATH{$Kind}) {
21237 exitStatus("Module_Error", "can't access \'".$RULES_PATH{$Kind}."\'");
21238 }
21239 my $Content = readFile($RULES_PATH{$Kind});
21240 while(my $Rule = parseTag(\$Content, "rule"))
21241 {
21242 my $RId = parseTag(\$Rule, "id");
21243 my @Properties = ("Severity", "Change", "Effect", "Overcome", "Kind");
21244 foreach my $Prop (@Properties) {
21245 if(my $Value = parseTag(\$Rule, lc($Prop)))
21246 {
21247 $Value=~s/\n[ ]*//;
21248 $CompatRules{$Kind}{$RId}{$Prop} = $Value;
21249 }
21250 }
21251 if($CompatRules{$Kind}{$RId}{"Kind"}=~/\A(Symbols|Parameters)\Z/) {
21252 $CompatRules{$Kind}{$RId}{"Kind"} = "Symbols";
21253 }
21254 else {
21255 $CompatRules{$Kind}{$RId}{"Kind"} = "Types";
21256 }
21257 }
21258}
21259
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021260sub getReportPath($)
21261{
21262 my $Level = $_[0];
21263 my $Dir = "compat_reports/$TargetLibraryName/".$Descriptor{1}{"Version"}."_to_".$Descriptor{2}{"Version"};
21264 if($Level eq "Binary")
21265 {
21266 if($BinaryReportPath)
21267 { # --bin-report-path
21268 return $BinaryReportPath;
21269 }
21270 elsif($OutputReportPath)
21271 { # --report-path
21272 return $OutputReportPath;
21273 }
21274 else
21275 { # default
21276 return $Dir."/abi_compat_report.$ReportFormat";
21277 }
21278 }
21279 elsif($Level eq "Source")
21280 {
21281 if($SourceReportPath)
21282 { # --src-report-path
21283 return $SourceReportPath;
21284 }
21285 elsif($OutputReportPath)
21286 { # --report-path
21287 return $OutputReportPath;
21288 }
21289 else
21290 { # default
21291 return $Dir."/src_compat_report.$ReportFormat";
21292 }
21293 }
21294 else
21295 {
21296 if($OutputReportPath)
21297 { # --report-path
21298 return $OutputReportPath;
21299 }
21300 else
21301 { # default
21302 return $Dir."/compat_report.$ReportFormat";
21303 }
21304 }
21305}
21306
21307sub printStatMsg($)
21308{
21309 my $Level = $_[0];
21310 printMsg("INFO", "total \"$Level\" compatibility problems: ".$RESULT{$Level}{"Problems"}.", warnings: ".$RESULT{$Level}{"Warnings"});
21311}
21312
21313sub listAffected($)
21314{
21315 my $Level = $_[0];
21316 my $List = "";
21317 foreach (keys(%{$TotalAffected{$Level}}))
21318 {
21319 if($StrictCompat and $TotalAffected{$Level}{$_} eq "Low")
21320 { # skip "Low"-severity problems
21321 next;
21322 }
21323 $List .= "$_\n";
21324 }
21325 my $Dir = get_dirname(getReportPath($Level));
21326 if($Level eq "Binary") {
21327 writeFile($Dir."/abi_affected.txt", $List);
21328 }
21329 elsif($Level eq "Source") {
21330 writeFile($Dir."/src_affected.txt", $List);
21331 }
21332}
21333
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021334sub printReport()
21335{
21336 printMsg("INFO", "creating compatibility report ...");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021337 createReport();
21338 if($JoinReport or $DoubleReport)
21339 {
21340 if($RESULT{"Binary"}{"Problems"}
21341 or $RESULT{"Source"}{"Problems"}) {
21342 printMsg("INFO", "result: INCOMPATIBLE (Binary: ".$RESULT{"Binary"}{"Affected"}."\%, Source: ".$RESULT{"Source"}{"Affected"}."\%)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021343 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021344 else {
21345 printMsg("INFO", "result: COMPATIBLE");
21346 }
21347 printStatMsg("Binary");
21348 printStatMsg("Source");
21349 if($ListAffected)
21350 { # --list-affected
21351 listAffected("Binary");
21352 listAffected("Source");
21353 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021354 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021355 elsif($BinaryOnly)
21356 {
21357 if($RESULT{"Binary"}{"Problems"}) {
21358 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Binary"}{"Affected"}."\%)");
21359 }
21360 else {
21361 printMsg("INFO", "result: COMPATIBLE");
21362 }
21363 printStatMsg("Binary");
21364 if($ListAffected)
21365 { # --list-affected
21366 listAffected("Binary");
21367 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021368 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021369 elsif($SourceOnly)
21370 {
21371 if($RESULT{"Source"}{"Problems"}) {
21372 printMsg("INFO", "result: INCOMPATIBLE (".$RESULT{"Source"}{"Affected"}."\%)");
21373 }
21374 else {
21375 printMsg("INFO", "result: COMPATIBLE");
21376 }
21377 printStatMsg("Source");
21378 if($ListAffected)
21379 { # --list-affected
21380 listAffected("Source");
21381 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021382 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021383 if($StdOut)
21384 {
21385 if($JoinReport or not $DoubleReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021386 { # --binary or --source
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021387 printMsg("INFO", "compatibility report has been generated to stdout");
21388 }
21389 else
21390 { # default
21391 printMsg("INFO", "compatibility reports have been generated to stdout");
21392 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021393 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021394 else
21395 {
21396 if($JoinReport)
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021397 {
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021398 printMsg("INFO", "see detailed report:\n ".getReportPath("Join"));
21399 }
21400 elsif($DoubleReport)
21401 { # default
21402 printMsg("INFO", "see detailed reports:\n ".getReportPath("Binary")."\n ".getReportPath("Source"));
21403 }
21404 elsif($BinaryOnly)
21405 { # --binary
21406 printMsg("INFO", "see detailed report:\n ".getReportPath("Binary"));
21407 }
21408 elsif($SourceOnly)
21409 { # --source
21410 printMsg("INFO", "see detailed report:\n ".getReportPath("Source"));
21411 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021412 }
21413}
21414
21415sub check_win32_env()
21416{
21417 if(not $ENV{"DevEnvDir"}
21418 or not $ENV{"LIB"}) {
21419 exitStatus("Error", "can't start without VS environment (vsvars32.bat)");
21420 }
21421}
21422
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021423sub diffSets($$)
21424{
21425 my ($S1, $S2) = @_;
21426 my @SK1 = keys(%{$S1});
21427 my @SK2 = keys(%{$S2});
21428 if($#SK1!=$#SK2) {
21429 return 1;
21430 }
21431 foreach my $K1 (@SK1)
21432 {
21433 if(not defined $S2->{$K1}) {
21434 return 1;
21435 }
21436 }
21437 return 0;
21438}
21439
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021440sub create_ABI_Dump()
21441{
21442 if(not -e $DumpAPI) {
21443 exitStatus("Access_Error", "can't access \'$DumpAPI\'");
21444 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021445 my @DParts = split(/\s*,\s*/, $DumpAPI);
21446 foreach my $Part (@DParts)
21447 {
21448 if(not -e $Part) {
21449 exitStatus("Access_Error", "can't access \'$Part\'");
21450 }
21451 }
21452 checkVersionNum(1, $DumpAPI);
21453 foreach my $Part (@DParts)
21454 {
21455 if(isDump($Part)) {
21456 read_ABI_Dump(1, $Part);
21457 }
21458 else {
21459 readDescriptor(1, createDescriptor(1, $Part));
21460 }
21461 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021462
21463 if(not $Descriptor{1}{"Version"})
21464 { # set to default: X
21465 $Descriptor{1}{"Version"} = "X";
21466 }
21467
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021468 initLogging(1);
21469 detect_default_paths("inc|lib|bin|gcc"); # complete analysis
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021470
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021471 my $DumpPath = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi";
21472 $DumpPath .= ".".$AR_EXT; # gzipped by default
21473 if($OutputDumpPath)
21474 { # user defined path
21475 $DumpPath = $OutputDumpPath;
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021476 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021477 my $Archive = ($DumpPath=~s/\Q.$AR_EXT\E\Z//g);
21478
21479 if(not $Archive and not $StdOut)
21480 { # check archive utilities
21481 if($OSgroup eq "windows")
21482 { # using zip
21483 my $ZipCmd = get_CmdPath("zip");
21484 if(not $ZipCmd) {
21485 exitStatus("Not_Found", "can't find \"zip\"");
21486 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021487 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040021488 else
21489 { # using tar and gzip
21490 my $TarCmd = get_CmdPath("tar");
21491 if(not $TarCmd) {
21492 exitStatus("Not_Found", "can't find \"tar\"");
21493 }
21494 my $GzipCmd = get_CmdPath("gzip");
21495 if(not $GzipCmd) {
21496 exitStatus("Not_Found", "can't find \"gzip\"");
21497 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021498 }
21499 }
21500
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021501 if(not $Descriptor{1}{"Dump"})
21502 {
21503 if(not $CheckHeadersOnly) {
21504 readLibs(1);
21505 }
21506 if($CheckHeadersOnly) {
21507 setLanguage(1, "C++");
21508 }
21509 if(not $CheckObjectsOnly) {
21510 searchForHeaders(1);
21511 }
21512 $WORD_SIZE{1} = detectWordSize();
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021513 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021514 if(not $Descriptor{1}{"Dump"})
21515 {
21516 if($Descriptor{1}{"Headers"}) {
21517 readHeaders(1);
21518 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021519 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021520 cleanDump(1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021521 if(not keys(%{$SymbolInfo{1}}))
21522 { # check if created dump is valid
21523 if(not $ExtendedCheck and not $CheckObjectsOnly)
21524 {
21525 if($CheckHeadersOnly) {
21526 exitStatus("Empty_Set", "the set of public symbols is empty");
21527 }
21528 else {
21529 exitStatus("Empty_Intersection", "the sets of public symbols in headers and libraries have empty intersection");
21530 }
21531 }
21532 }
21533 my %HeadersInfo = ();
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021534 foreach my $HPath (keys(%{$Registered_Headers{1}})) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021535 $HeadersInfo{$Registered_Headers{1}{$HPath}{"Identity"}} = $Registered_Headers{1}{$HPath}{"Pos"};
21536 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040021537 if($ExtraDump)
21538 { # add unmangled names to the ABI dump
21539 my @Names = ();
21540 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21541 {
21542 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"}) {
21543 push(@Names, $MnglName);
21544 }
21545 }
21546 translateSymbols(@Names, 1);
21547 foreach my $InfoId (keys(%{$SymbolInfo{1}}))
21548 {
21549 if(my $MnglName = $SymbolInfo{1}{$InfoId}{"MnglName"})
21550 {
21551 if(my $Unmangled = $tr_name{$MnglName})
21552 {
21553 if($MnglName ne $Unmangled) {
21554 $SymbolInfo{1}{$InfoId}{"Unmangled"} = $Unmangled;
21555 }
21556 }
21557 }
21558 }
21559 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021560
21561 my %GccConstants = (); # built-in GCC constants
21562 foreach my $Name (keys(%{$Constants{1}}))
21563 {
21564 if(not defined $Constants{1}{$Name}{"Header"})
21565 {
21566 $GccConstants{$Name} = $Constants{1}{$Name}{"Value"};
21567 delete($Constants{1}{$Name});
21568 }
21569 }
21570
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021571 printMsg("INFO", "creating library ABI dump ...");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021572 my %ABI = (
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021573 "TypeInfo" => $TypeInfo{1},
21574 "SymbolInfo" => $SymbolInfo{1},
21575 "Symbols" => $Library_Symbol{1},
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021576 "DepSymbols" => $DepLibrary_Symbol{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021577 "SymbolVersion" => $SymVer{1},
21578 "LibraryVersion" => $Descriptor{1}{"Version"},
21579 "LibraryName" => $TargetLibraryName,
21580 "Language" => $COMMON_LANGUAGE{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021581 "SkipTypes" => $SkipTypes{1},
21582 "SkipSymbols" => $SkipSymbols{1},
21583 "SkipNameSpaces" => $SkipNameSpaces{1},
21584 "SkipHeaders" => $SkipHeadersList{1},
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021585 "Headers" => \%HeadersInfo,
21586 "Constants" => $Constants{1},
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021587 "GccConstants" => \%GccConstants,
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021588 "NameSpaces" => $NestedNameSpaces{1},
21589 "Target" => $OStarget,
21590 "Arch" => getArch(1),
21591 "WordSize" => $WORD_SIZE{1},
21592 "GccVersion" => get_dumpversion($GCC_PATH),
21593 "ABI_DUMP_VERSION" => $ABI_DUMP_VERSION,
21594 "ABI_COMPLIANCE_CHECKER_VERSION" => $TOOL_VERSION
21595 );
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021596 if(diffSets($TargetHeaders{1}, \%HeadersInfo)) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021597 $ABI{"TargetHeaders"} = $TargetHeaders{1};
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021598 }
21599 if($UseXML) {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021600 $ABI{"XML_ABI_DUMP_VERSION"} = $XML_ABI_DUMP_VERSION;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021601 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021602 if($ExtendedCheck)
21603 { # --ext option
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021604 $ABI{"Mode"} = "Extended";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021605 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021606 if($BinaryOnly)
21607 { # --binary
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021608 $ABI{"BinOnly"} = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021609 }
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021610 if($ExtraDump)
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021611 { # --extra-dump
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021612 $ABI{"Extra"} = 1;
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021613 $ABI{"UndefinedSymbols"} = $UndefinedSymbols{1};
21614 $ABI{"Needed"} = $Library_Needed{1};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021615 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021616
21617 my $ABI_DUMP = "";
21618 if($UseXML)
21619 {
21620 loadModule("XmlDump");
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021621 $ABI_DUMP = createXmlDump(\%ABI);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021622 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021623 else
21624 { # default
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021625 $ABI_DUMP = Dumper(\%ABI);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021626 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021627 if($StdOut)
21628 { # --stdout option
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021629 print STDOUT $ABI_DUMP;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021630 printMsg("INFO", "ABI dump has been generated to stdout");
21631 return;
21632 }
21633 else
21634 { # write to gzipped file
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021635 my ($DDir, $DName) = separate_path($DumpPath);
21636 my $DPath = $TMP_DIR."/".$DName;
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021637 if(not $Archive) {
21638 $DPath = $DumpPath;
21639 }
21640
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021641 mkpath($DDir);
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021642
21643 open(DUMP, ">", $DPath) || die ("can't open file \'$DPath\': $!\n");
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021644 print DUMP $ABI_DUMP;
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021645 close(DUMP);
21646
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021647 if(not -s $DPath) {
21648 exitStatus("Error", "can't create ABI dump because something is going wrong with the Data::Dumper module");
21649 }
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021650 if($Archive) {
21651 $DumpPath = createArchive($DPath, $DDir);
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040021652 }
21653
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021654 if($OutputDumpPath) {
21655 printMsg("INFO", "library ABI has been dumped to:\n $OutputDumpPath");
Andrey Ponomarenko07aea072012-11-12 16:15:07 +040021656 }
Andrey Ponomarenkoed178382013-06-07 16:07:44 +040021657 else {
21658 printMsg("INFO", "library ABI has been dumped to:\n $DumpPath");
21659 }
21660 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 +040021661 }
21662}
21663
21664sub quickEmptyReports()
21665{ # Quick "empty" reports
21666 # 4 times faster than merging equal dumps
21667 # NOTE: the dump contains the "LibraryVersion" attribute
21668 # if you change the version, then your dump will be different
21669 # OVERCOME: use -v1 and v2 options for comparing dumps
21670 # and don't change version in the XML descriptor (and dumps)
21671 # OVERCOME 2: separate meta info from the dumps in ACC 2.0
21672 if(-s $Descriptor{1}{"Path"} == -s $Descriptor{2}{"Path"})
21673 {
21674 my $FilePath1 = unpackDump($Descriptor{1}{"Path"});
21675 my $FilePath2 = unpackDump($Descriptor{2}{"Path"});
21676 if($FilePath1 and $FilePath2)
21677 {
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021678 my $Line = readLineNum($FilePath1, 0);
21679 if($Line=~/xml/)
21680 { # XML format
21681 # is not supported yet
21682 return;
21683 }
21684
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021685 local $/ = undef;
21686
21687 open(DUMP1, $FilePath1);
21688 my $Content1 = <DUMP1>;
21689 close(DUMP1);
21690
21691 open(DUMP2, $FilePath2);
21692 my $Content2 = <DUMP2>;
21693 close(DUMP2);
21694
21695 if($Content1 eq $Content2)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021696 {
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021697 # clean memory
21698 undef $Content2;
21699
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021700 # read a number of headers, libs, symbols and types
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021701 my $ABIdump = eval($Content1);
21702
21703 # clean memory
21704 undef $Content1;
21705
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021706 if(not $ABIdump) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021707 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 +040021708 }
21709 if(not $ABIdump->{"TypeInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021710 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021711 $ABIdump->{"TypeInfo"} = $ABIdump->{"TypeDescr"};
21712 }
21713 if(not $ABIdump->{"SymbolInfo"})
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021714 { # support for old dumps
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021715 $ABIdump->{"SymbolInfo"} = $ABIdump->{"FuncDescr"};
21716 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021717 read_Source_DumpInfo($ABIdump, 1);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021718 read_Libs_DumpInfo($ABIdump, 1);
21719 read_Machine_DumpInfo($ABIdump, 1);
21720 read_Machine_DumpInfo($ABIdump, 2);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021721
21722 %{$CheckedTypes{"Binary"}} = %{$ABIdump->{"TypeInfo"}};
21723 %{$CheckedTypes{"Source"}} = %{$ABIdump->{"TypeInfo"}};
21724
21725 %{$CheckedSymbols{"Binary"}} = %{$ABIdump->{"SymbolInfo"}};
21726 %{$CheckedSymbols{"Source"}} = %{$ABIdump->{"SymbolInfo"}};
21727
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021728 $Descriptor{1}{"Version"} = $TargetVersion{1}?$TargetVersion{1}:$ABIdump->{"LibraryVersion"};
21729 $Descriptor{2}{"Version"} = $TargetVersion{2}?$TargetVersion{2}:$ABIdump->{"LibraryVersion"};
21730 exitReport();
21731 }
21732 }
21733 }
21734}
21735
21736sub initLogging($)
21737{
21738 my $LibVersion = $_[0];
21739 # create log directory
21740 my ($LOG_DIR, $LOG_FILE) = ("logs/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"}, "log.txt");
21741 if($OutputLogPath{$LibVersion})
21742 { # user-defined by -log-path option
21743 ($LOG_DIR, $LOG_FILE) = separate_path($OutputLogPath{$LibVersion});
21744 }
21745 if($LogMode ne "n") {
21746 mkpath($LOG_DIR);
21747 }
21748 $LOG_PATH{$LibVersion} = get_abs_path($LOG_DIR)."/".$LOG_FILE;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021749 if($Debug)
21750 { # debug directory
21751 $DEBUG_PATH{$LibVersion} = "debug/$TargetLibraryName/".$Descriptor{$LibVersion}{"Version"};
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021752
21753 if(not $ExtraInfo)
21754 { # enable --extra-info
21755 $ExtraInfo = $DEBUG_PATH{$LibVersion}."/extra-info";
21756 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021757 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021758 resetLogging($LibVersion);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021759}
21760
21761sub writeLog($$)
21762{
21763 my ($LibVersion, $Msg) = @_;
21764 if($LogMode ne "n") {
21765 appendFile($LOG_PATH{$LibVersion}, $Msg);
21766 }
21767}
21768
21769sub resetLogging($)
21770{
21771 my $LibVersion = $_[0];
21772 if($LogMode!~/a|n/)
21773 { # remove old log
21774 unlink($LOG_PATH{$LibVersion});
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040021775 if($Debug) {
21776 rmtree($DEBUG_PATH{$LibVersion});
21777 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021778 }
21779}
21780
21781sub printErrorLog($)
21782{
21783 my $LibVersion = $_[0];
21784 if($LogMode ne "n") {
21785 printMsg("ERROR", "see log for details:\n ".$LOG_PATH{$LibVersion}."\n");
21786 }
21787}
21788
21789sub isDump($)
21790{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021791 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.tar\.gz|\.zip|\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040021792 return $1;
21793 }
21794 return 0;
21795}
21796
21797sub isDump_U($)
21798{
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021799 if(get_filename($_[0])=~/\A(.+)\.(abi|abidump|dump)(\.xml|)(\.\w+|)\Z/) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021800 return $1;
21801 }
21802 return 0;
21803}
21804
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040021805sub compareInit()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021806{
21807 # read input XML descriptors or ABI dumps
21808 if(not $Descriptor{1}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021809 exitStatus("Error", "-old option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021810 }
21811 my @DParts1 = split(/\s*,\s*/, $Descriptor{1}{"Path"});
21812 foreach my $Part (@DParts1)
21813 {
21814 if(not -e $Part) {
21815 exitStatus("Access_Error", "can't access \'$Part\'");
21816 }
21817 }
21818 if(not $Descriptor{2}{"Path"}) {
Andrey Ponomarenko0d5917f2012-04-16 16:44:09 +040021819 exitStatus("Error", "-new option is not specified");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021820 }
21821 my @DParts2 = split(/\s*,\s*/, $Descriptor{2}{"Path"});
21822 foreach my $Part (@DParts2)
21823 {
21824 if(not -e $Part) {
21825 exitStatus("Access_Error", "can't access \'$Part\'");
21826 }
21827 }
21828 detect_default_paths("bin"); # to extract dumps
21829 if($#DParts1==0 and $#DParts2==0
21830 and isDump($Descriptor{1}{"Path"})
21831 and isDump($Descriptor{2}{"Path"}))
21832 { # optimization: equal ABI dumps
21833 quickEmptyReports();
21834 }
21835 checkVersionNum(1, $Descriptor{1}{"Path"});
21836 checkVersionNum(2, $Descriptor{2}{"Path"});
21837 printMsg("INFO", "preparation, please wait ...");
21838 foreach my $Part (@DParts1)
21839 {
21840 if(isDump($Part)) {
21841 read_ABI_Dump(1, $Part);
21842 }
21843 else {
21844 readDescriptor(1, createDescriptor(1, $Part));
21845 }
21846 }
21847 foreach my $Part (@DParts2)
21848 {
21849 if(isDump($Part)) {
21850 read_ABI_Dump(2, $Part);
21851 }
21852 else {
21853 readDescriptor(2, createDescriptor(2, $Part));
21854 }
21855 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040021856
21857 if(not $Descriptor{1}{"Version"})
21858 { # set to default: X
21859 $Descriptor{1}{"Version"} = "X";
21860 }
21861
21862 if(not $Descriptor{2}{"Version"})
21863 { # set to default: Y
21864 $Descriptor{2}{"Version"} = "Y";
21865 }
21866
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021867 initLogging(1);
21868 initLogging(2);
21869 # check consistency
21870 if(not $Descriptor{1}{"Headers"}
21871 and not $Descriptor{1}{"Libs"}) {
21872 exitStatus("Error", "descriptor d1 does not contain both header files and libraries info");
21873 }
21874 if(not $Descriptor{2}{"Headers"}
21875 and not $Descriptor{2}{"Libs"}) {
21876 exitStatus("Error", "descriptor d2 does not contain both header files and libraries info");
21877 }
21878 if($Descriptor{1}{"Headers"} and not $Descriptor{1}{"Libs"}
21879 and not $Descriptor{2}{"Headers"} and $Descriptor{2}{"Libs"}) {
21880 exitStatus("Error", "can't compare headers with $SLIB_TYPE libraries");
21881 }
21882 elsif(not $Descriptor{1}{"Headers"} and $Descriptor{1}{"Libs"}
21883 and $Descriptor{2}{"Headers"} and not $Descriptor{2}{"Libs"}) {
21884 exitStatus("Error", "can't compare $SLIB_TYPE libraries with headers");
21885 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021886 if(not $Descriptor{1}{"Headers"})
21887 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021888 if($CheckHeadersOnly_Opt) {
21889 exitStatus("Error", "can't find header files info in descriptor d1");
21890 }
21891 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021892 if(not $Descriptor{2}{"Headers"})
21893 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021894 if($CheckHeadersOnly_Opt) {
21895 exitStatus("Error", "can't find header files info in descriptor d2");
21896 }
21897 }
21898 if(not $Descriptor{1}{"Headers"}
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021899 or not $Descriptor{2}{"Headers"})
21900 {
21901 if(not $CheckObjectsOnly_Opt)
21902 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021903 printMsg("WARNING", "comparing $SLIB_TYPE libraries only");
21904 $CheckObjectsOnly = 1;
21905 }
21906 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021907 if(not $Descriptor{1}{"Libs"})
21908 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021909 if($CheckObjectsOnly_Opt) {
21910 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d1");
21911 }
21912 }
Andrey Ponomarenkobdc85a92012-11-12 17:28:12 +040021913 if(not $Descriptor{2}{"Libs"})
21914 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021915 if($CheckObjectsOnly_Opt) {
21916 exitStatus("Error", "can't find $SLIB_TYPE libraries info in descriptor d2");
21917 }
21918 }
21919 if(not $Descriptor{1}{"Libs"}
21920 or not $Descriptor{2}{"Libs"})
21921 { # comparing standalone header files
21922 # comparing ABI dumps created with --headers-only
21923 if(not $CheckHeadersOnly_Opt)
21924 {
21925 printMsg("WARNING", "checking headers only");
21926 $CheckHeadersOnly = 1;
21927 }
21928 }
21929 if($UseDumps)
21930 { # --use-dumps
21931 # parallel processing
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021932 my $DumpPath1 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{1}{"Version"}.".abi.$AR_EXT";
21933 my $DumpPath2 = "abi_dumps/$TargetLibraryName/".$TargetLibraryName."_".$Descriptor{2}{"Version"}.".abi.$AR_EXT";
21934
21935 unlink($DumpPath1);
21936 unlink($DumpPath2);
21937
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021938 my $pid = fork();
21939 if($pid)
21940 { # dump on two CPU cores
21941 my @PARAMS = ("-dump", $Descriptor{1}{"Path"}, "-l", $TargetLibraryName);
21942 if($RelativeDirectory{1}) {
21943 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{1});
21944 }
21945 if($OutputLogPath{1}) {
21946 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{1});
21947 }
21948 if($CrossGcc) {
21949 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
21950 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021951 if($Quiet)
21952 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021953 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040021954 @PARAMS = (@PARAMS, "-logging-mode", "a");
21955 }
21956 elsif($LogMode and $LogMode ne "w")
21957 { # "w" is default
21958 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021959 }
21960 if($ExtendedCheck) {
21961 @PARAMS = (@PARAMS, "-extended");
21962 }
21963 if($UserLang) {
21964 @PARAMS = (@PARAMS, "-lang", $UserLang);
21965 }
21966 if($TargetVersion{1}) {
21967 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{1});
21968 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021969 if($BinaryOnly) {
21970 @PARAMS = (@PARAMS, "-binary");
21971 }
21972 if($SourceOnly) {
21973 @PARAMS = (@PARAMS, "-source");
21974 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021975 if($SortDump) {
21976 @PARAMS = (@PARAMS, "-sort");
21977 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040021978 if($DumpFormat and $DumpFormat ne "perl") {
21979 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
21980 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040021981 if($CheckHeadersOnly) {
21982 @PARAMS = (@PARAMS, "-headers-only");
21983 }
21984 if($CheckObjectsOnly) {
21985 @PARAMS = (@PARAMS, "-objects-only");
21986 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021987 if($Debug)
21988 {
21989 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040021990 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040021991 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021992 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040021993 if(not -f $DumpPath1) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040021994 exit(1);
21995 }
21996 }
21997 else
21998 { # child
21999 my @PARAMS = ("-dump", $Descriptor{2}{"Path"}, "-l", $TargetLibraryName);
22000 if($RelativeDirectory{2}) {
22001 @PARAMS = (@PARAMS, "-relpath", $RelativeDirectory{2});
22002 }
22003 if($OutputLogPath{2}) {
22004 @PARAMS = (@PARAMS, "-log-path", $OutputLogPath{2});
22005 }
22006 if($CrossGcc) {
22007 @PARAMS = (@PARAMS, "-cross-gcc", $CrossGcc);
22008 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022009 if($Quiet)
22010 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022011 @PARAMS = (@PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022012 @PARAMS = (@PARAMS, "-logging-mode", "a");
22013 }
22014 elsif($LogMode and $LogMode ne "w")
22015 { # "w" is default
22016 @PARAMS = (@PARAMS, "-logging-mode", $LogMode);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022017 }
22018 if($ExtendedCheck) {
22019 @PARAMS = (@PARAMS, "-extended");
22020 }
22021 if($UserLang) {
22022 @PARAMS = (@PARAMS, "-lang", $UserLang);
22023 }
22024 if($TargetVersion{2}) {
22025 @PARAMS = (@PARAMS, "-vnum", $TargetVersion{2});
22026 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022027 if($BinaryOnly) {
22028 @PARAMS = (@PARAMS, "-binary");
22029 }
22030 if($SourceOnly) {
22031 @PARAMS = (@PARAMS, "-source");
22032 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022033 if($SortDump) {
22034 @PARAMS = (@PARAMS, "-sort");
22035 }
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022036 if($DumpFormat and $DumpFormat ne "perl") {
22037 @PARAMS = (@PARAMS, "-dump-format", $DumpFormat);
22038 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022039 if($CheckHeadersOnly) {
22040 @PARAMS = (@PARAMS, "-headers-only");
22041 }
22042 if($CheckObjectsOnly) {
22043 @PARAMS = (@PARAMS, "-objects-only");
22044 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022045 if($Debug)
22046 {
22047 @PARAMS = (@PARAMS, "-debug");
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022048 printMsg("INFO", "running perl $0 @PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022049 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022050 system("perl", $0, @PARAMS);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022051 if(not -f $DumpPath2) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022052 exit(1);
22053 }
22054 else {
22055 exit(0);
22056 }
22057 }
22058 waitpid($pid, 0);
22059 my @CMP_PARAMS = ("-l", $TargetLibraryName);
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022060 @CMP_PARAMS = (@CMP_PARAMS, "-d1", $DumpPath1);
22061 @CMP_PARAMS = (@CMP_PARAMS, "-d2", $DumpPath2);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022062 if($TargetLibraryFName ne $TargetLibraryName) {
22063 @CMP_PARAMS = (@CMP_PARAMS, "-l-full", $TargetLibraryFName);
22064 }
22065 if($ShowRetVal) {
22066 @CMP_PARAMS = (@CMP_PARAMS, "-show-retval");
22067 }
22068 if($CrossGcc) {
22069 @CMP_PARAMS = (@CMP_PARAMS, "-cross-gcc", $CrossGcc);
22070 }
Andrey Ponomarenko35c44fd2012-06-18 17:50:25 +040022071 @CMP_PARAMS = (@CMP_PARAMS, "-logging-mode", "a");
22072 if($Quiet) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022073 @CMP_PARAMS = (@CMP_PARAMS, "-quiet");
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022074 }
22075 if($ReportFormat and $ReportFormat ne "html")
22076 { # HTML is default format
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022077 @CMP_PARAMS = (@CMP_PARAMS, "-report-format", $ReportFormat);
22078 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022079 if($OutputReportPath) {
22080 @CMP_PARAMS = (@CMP_PARAMS, "-report-path", $OutputReportPath);
22081 }
22082 if($BinaryReportPath) {
22083 @CMP_PARAMS = (@CMP_PARAMS, "-bin-report-path", $BinaryReportPath);
22084 }
22085 if($SourceReportPath) {
22086 @CMP_PARAMS = (@CMP_PARAMS, "-src-report-path", $SourceReportPath);
22087 }
22088 if($LoggingPath) {
22089 @CMP_PARAMS = (@CMP_PARAMS, "-log-path", $LoggingPath);
22090 }
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022091 if($CheckHeadersOnly) {
22092 @CMP_PARAMS = (@CMP_PARAMS, "-headers-only");
22093 }
22094 if($CheckObjectsOnly) {
22095 @CMP_PARAMS = (@CMP_PARAMS, "-objects-only");
22096 }
22097 if($BinaryOnly) {
22098 @CMP_PARAMS = (@CMP_PARAMS, "-binary");
22099 }
22100 if($SourceOnly) {
22101 @CMP_PARAMS = (@CMP_PARAMS, "-source");
22102 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022103 if($Browse) {
22104 @CMP_PARAMS = (@CMP_PARAMS, "-browse", $Browse);
22105 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022106 if($OpenReport) {
22107 @CMP_PARAMS = (@CMP_PARAMS, "-open");
22108 }
22109 if($Debug)
22110 {
22111 @CMP_PARAMS = (@CMP_PARAMS, "-debug");
22112 printMsg("INFO", "running perl $0 @CMP_PARAMS");
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022113 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022114 system("perl", $0, @CMP_PARAMS);
22115 exit($?>>8);
22116 }
22117 if(not $Descriptor{1}{"Dump"}
22118 or not $Descriptor{2}{"Dump"})
22119 { # need GCC toolchain to analyze
22120 # header files and libraries
22121 detect_default_paths("inc|lib|gcc");
22122 }
22123 if(not $Descriptor{1}{"Dump"})
22124 {
22125 if(not $CheckHeadersOnly) {
22126 readLibs(1);
22127 }
22128 if($CheckHeadersOnly) {
22129 setLanguage(1, "C++");
22130 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022131 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022132 searchForHeaders(1);
22133 }
22134 $WORD_SIZE{1} = detectWordSize();
22135 }
22136 if(not $Descriptor{2}{"Dump"})
22137 {
22138 if(not $CheckHeadersOnly) {
22139 readLibs(2);
22140 }
22141 if($CheckHeadersOnly) {
22142 setLanguage(2, "C++");
22143 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022144 if(not $CheckObjectsOnly) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022145 searchForHeaders(2);
22146 }
22147 $WORD_SIZE{2} = detectWordSize();
22148 }
22149 if($WORD_SIZE{1} ne $WORD_SIZE{2})
22150 { # support for old ABI dumps
22151 # try to synch different WORD sizes
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022152 if(not checkDump(1, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022153 {
22154 $WORD_SIZE{1} = $WORD_SIZE{2};
22155 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{2}." bytes");
22156 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022157 elsif(not checkDump(2, "2.1"))
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022158 {
22159 $WORD_SIZE{2} = $WORD_SIZE{1};
22160 printMsg("WARNING", "set WORD size to ".$WORD_SIZE{1}." bytes");
22161 }
22162 }
22163 elsif(not $WORD_SIZE{1}
22164 and not $WORD_SIZE{2})
22165 { # support for old ABI dumps
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022166 $WORD_SIZE{1} = "4";
22167 $WORD_SIZE{2} = "4";
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022168 }
22169 if($Descriptor{1}{"Dump"})
22170 { # support for old ABI dumps
22171 prepareTypes(1);
22172 }
22173 if($Descriptor{2}{"Dump"})
22174 { # support for old ABI dumps
22175 prepareTypes(2);
22176 }
22177 if($AppPath and not keys(%{$Symbol_Library{1}})) {
22178 printMsg("WARNING", "the application ".get_filename($AppPath)." has no symbols imported from the $SLIB_TYPE libraries");
22179 }
22180 # started to process input data
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022181 if(not $CheckObjectsOnly)
22182 {
22183 if($Descriptor{1}{"Headers"}
22184 and not $Descriptor{1}{"Dump"}) {
22185 readHeaders(1);
22186 }
22187 if($Descriptor{2}{"Headers"}
22188 and not $Descriptor{2}{"Dump"}) {
22189 readHeaders(2);
22190 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022191 }
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022192
22193 # clean memory
22194 %SystemHeaders = ();
22195 %mangled_name_gcc = ();
22196
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022197 prepareSymbols(1);
22198 prepareSymbols(2);
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022199
Andrey Ponomarenko85043792012-05-14 16:48:07 +040022200 # clean memory
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022201 %SymbolInfo = ();
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022202
22203 # Virtual Tables
22204 registerVTable(1);
22205 registerVTable(2);
22206
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022207 if(not checkDump(1, "1.22")
22208 and checkDump(2, "1.22"))
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022209 { # support for old ABI dumps
22210 foreach my $ClassName (keys(%{$VirtualTable{2}}))
22211 {
22212 if($ClassName=~/</)
22213 { # templates
22214 if(not defined $VirtualTable{1}{$ClassName})
22215 { # synchronize
22216 delete($VirtualTable{2}{$ClassName});
22217 }
22218 }
22219 }
22220 }
22221
22222 registerOverriding(1);
22223 registerOverriding(2);
22224
22225 setVirtFuncPositions(1);
22226 setVirtFuncPositions(2);
22227
22228 # Other
22229 addParamNames(1);
22230 addParamNames(2);
22231
22232 detectChangedTypedefs();
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022233}
22234
22235sub compareAPIs($)
22236{
22237 my $Level = $_[0];
22238 readRules($Level);
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022239 loadModule("CallConv");
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022240 if($Level eq "Binary") {
22241 printMsg("INFO", "comparing ABIs ...");
22242 }
22243 else {
22244 printMsg("INFO", "comparing APIs ...");
22245 }
22246 if($CheckHeadersOnly
22247 or $Level eq "Source")
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022248 { # added/removed in headers
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022249 detectAdded_H($Level);
22250 detectRemoved_H($Level);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022251 }
22252 else
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022253 { # added/removed in libs
22254 detectAdded($Level);
22255 detectRemoved($Level);
22256 }
22257 if(not $CheckObjectsOnly)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022258 {
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022259 mergeSymbols($Level);
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022260 if(keys(%{$CheckedSymbols{$Level}})) {
22261 mergeConstants($Level);
22262 }
22263 }
22264 if($CheckHeadersOnly
22265 or $Level eq "Source")
22266 { # added/removed in headers
22267 mergeHeaders($Level);
22268 }
22269 else
22270 { # added/removed in libs
22271 mergeLibs($Level);
22272 if($CheckImpl
22273 and $Level eq "Binary") {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022274 mergeImpl();
22275 }
22276 }
22277}
22278
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022279sub getSysOpts()
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022280{
22281 my %Opts = (
22282 "OStarget"=>$OStarget,
22283 "Debug"=>$Debug,
22284 "Quiet"=>$Quiet,
22285 "LogMode"=>$LogMode,
22286 "CheckHeadersOnly"=>$CheckHeadersOnly,
22287
22288 "SystemRoot"=>$SystemRoot,
22289 "MODULES_DIR"=>$MODULES_DIR,
22290 "GCC_PATH"=>$GCC_PATH,
22291 "TargetSysInfo"=>$TargetSysInfo,
22292 "CrossPrefix"=>$CrossPrefix,
22293 "TargetLibraryName"=>$TargetLibraryName,
22294 "CrossGcc"=>$CrossGcc,
22295 "UseStaticLibs"=>$UseStaticLibs,
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022296 "NoStdInc"=>$NoStdInc,
22297
22298 "BinaryOnly" => $BinaryOnly,
22299 "SourceOnly" => $SourceOnly
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022300 );
22301 return \%Opts;
22302}
22303
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022304sub get_CodeError($)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022305{
22306 my %CODE_ERROR = reverse(%ERROR_CODE);
22307 return $CODE_ERROR{$_[0]};
22308}
22309
22310sub scenario()
22311{
22312 if($StdOut)
22313 { # enable quiet mode
22314 $Quiet = 1;
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022315 $JoinReport = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022316 }
Andrey Ponomarenkodde2dad2012-03-26 19:06:14 +040022317 if(not $LogMode)
22318 { # default
22319 $LogMode = "w";
22320 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022321 if($UserLang)
22322 { # --lang=C++
22323 $UserLang = uc($UserLang);
22324 $COMMON_LANGUAGE{1}=$UserLang;
22325 $COMMON_LANGUAGE{2}=$UserLang;
22326 }
22327 if($LoggingPath)
22328 {
22329 $OutputLogPath{1} = $LoggingPath;
22330 $OutputLogPath{2} = $LoggingPath;
22331 if($Quiet) {
22332 $COMMON_LOG_PATH = $LoggingPath;
22333 }
22334 }
Andrey Ponomarenkoe3a8d812013-06-28 12:50:10 +040022335 if($Quick) {
22336 $ADD_TMPL_INSTANCES = 0;
22337 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022338 if($OutputDumpPath)
22339 { # validate
Andrey Ponomarenko74b33ee2012-12-14 15:24:09 +040022340 if(not isDump($OutputDumpPath)) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022341 exitStatus("Error", "the dump path should be a path to *.abi.$AR_EXT or *.abi file");
22342 }
22343 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022344 if($BinaryOnly and $SourceOnly)
22345 { # both --binary and --source
22346 # is the default mode
22347 $DoubleReport = 1;
22348 $JoinReport = 0;
22349 $BinaryOnly = 0;
22350 $SourceOnly = 0;
22351 if($OutputReportPath)
22352 { # --report-path
22353 $DoubleReport = 0;
22354 $JoinReport = 1;
22355 }
22356 }
22357 elsif($BinaryOnly or $SourceOnly)
22358 { # --binary or --source
22359 $DoubleReport = 0;
22360 $JoinReport = 0;
22361 }
22362 if($UseXML)
22363 { # --xml option
22364 $ReportFormat = "xml";
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022365 $DumpFormat = "xml";
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022366 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022367 if($ReportFormat)
22368 { # validate
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022369 $ReportFormat = lc($ReportFormat);
22370 if($ReportFormat!~/\A(xml|html|htm)\Z/) {
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022371 exitStatus("Error", "unknown report format \'$ReportFormat\'");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022372 }
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022373 if($ReportFormat eq "htm")
22374 { # HTM == HTML
22375 $ReportFormat = "html";
22376 }
22377 elsif($ReportFormat eq "xml")
22378 { # --report-format=XML equal to --xml
22379 $UseXML = 1;
22380 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022381 }
22382 else
22383 { # default: HTML
22384 $ReportFormat = "html";
22385 }
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022386 if($DumpFormat)
22387 { # validate
22388 $DumpFormat = lc($DumpFormat);
22389 if($DumpFormat!~/\A(xml|perl)\Z/) {
22390 exitStatus("Error", "unknown ABI dump format \'$DumpFormat\'");
22391 }
22392 if($DumpFormat eq "xml")
22393 { # --dump-format=XML equal to --xml
22394 $UseXML = 1;
22395 }
22396 }
22397 else
Andrey Ponomarenko01117f12012-06-26 12:23:02 +040022398 { # default: Perl Data::Dumper
Andrey Ponomarenko5c09ef32012-06-14 18:17:33 +040022399 $DumpFormat = "perl";
22400 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022401 if($Quiet and $LogMode!~/a|n/)
22402 { # --quiet log
22403 if(-f $COMMON_LOG_PATH) {
22404 unlink($COMMON_LOG_PATH);
22405 }
22406 }
Andrey Ponomarenko4b077f82012-12-04 16:04:36 +040022407 if($ExtraInfo) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022408 $CheckUndefined = 1;
22409 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022410 if($TestTool and $UseDumps)
22411 { # --test && --use-dumps == --test-dump
22412 $TestDump = 1;
22413 }
Andrey Ponomarenko8f4b9812013-02-07 19:11:42 +040022414 if($Tolerant)
22415 { # enable all
22416 $Tolerance = 1234;
22417 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022418 if($Help)
22419 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022420 HELP_MESSAGE();
22421 exit(0);
22422 }
22423 if($InfoMsg) {
22424 INFO_MESSAGE();
22425 exit(0);
22426 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022427 if($ShowVersion)
22428 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022429 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.");
22430 exit(0);
22431 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022432 if($DumpVersion)
22433 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022434 printMsg("INFO", $TOOL_VERSION);
22435 exit(0);
22436 }
22437 if($ExtendedCheck) {
22438 $CheckHeadersOnly = 1;
22439 }
22440 if($SystemRoot_Opt)
22441 { # user defined root
22442 if(not -e $SystemRoot_Opt) {
22443 exitStatus("Access_Error", "can't access \'$SystemRoot\'");
22444 }
22445 $SystemRoot = $SystemRoot_Opt;
22446 $SystemRoot=~s/[\/]+\Z//g;
22447 if($SystemRoot) {
22448 $SystemRoot = get_abs_path($SystemRoot);
22449 }
22450 }
22451 $Data::Dumper::Sortkeys = 1;
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022452
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022453 if($SortDump)
22454 {
22455 $Data::Dumper::Useperl = 1;
22456 $Data::Dumper::Sortkeys = \&dump_sorting;
22457 }
Andrey Ponomarenko989a50b2012-04-03 12:24:22 +040022458
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022459 if($TargetLibsPath)
22460 {
22461 if(not -f $TargetLibsPath) {
22462 exitStatus("Access_Error", "can't access file \'$TargetLibsPath\'");
22463 }
22464 foreach my $Lib (split(/\s*\n\s*/, readFile($TargetLibsPath))) {
22465 $TargetLibs{$Lib} = 1;
22466 }
22467 }
22468 if($TargetHeadersPath)
22469 { # --headers-list
22470 if(not -f $TargetHeadersPath) {
22471 exitStatus("Access_Error", "can't access file \'$TargetHeadersPath\'");
22472 }
22473 foreach my $Header (split(/\s*\n\s*/, readFile($TargetHeadersPath)))
22474 {
22475 $TargetHeaders{1}{$Header} = 1;
22476 $TargetHeaders{2}{$Header} = 1;
22477 }
22478 }
22479 if($TargetHeader)
22480 { # --header
22481 $TargetHeaders{1}{$TargetHeader} = 1;
22482 $TargetHeaders{2}{$TargetHeader} = 1;
22483 }
22484 if($TestTool
22485 or $TestDump)
22486 { # --test, --test-dump
22487 detect_default_paths("bin|gcc"); # to compile libs
22488 loadModule("RegTests");
Andrey Ponomarenkof48ec932012-07-19 18:57:20 +040022489 testTool($TestDump, $Debug, $Quiet, $ExtendedCheck, $LogMode, $ReportFormat, $DumpFormat,
22490 $LIB_EXT, $GCC_PATH, $Browse, $OpenReport, $SortDump, $CheckHeadersOnly, $CheckObjectsOnly);
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022491 exit(0);
22492 }
22493 if($DumpSystem)
22494 { # --dump-system
22495 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022496 if($DumpSystem=~/\.(xml|desc)\Z/)
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022497 { # system XML descriptor
22498 if(not -f $DumpSystem) {
22499 exitStatus("Access_Error", "can't access file \'$DumpSystem\'");
22500 }
22501 my $Ret = readSystemDescriptor(readFile($DumpSystem));
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022502 foreach (@{$Ret->{"Tools"}})
22503 {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022504 push_U($SystemPaths{"bin"}, $_);
22505 $TargetTools{$_} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022506 }
22507 if($Ret->{"CrossPrefix"}) {
22508 $CrossPrefix = $Ret->{"CrossPrefix"};
22509 }
22510 }
22511 elsif($SystemRoot_Opt)
22512 { # -sysroot "/" option
22513 # default target: /usr/lib, /usr/include
22514 # search libs: /usr/lib and /lib
22515 if(not -e $SystemRoot."/usr/lib") {
22516 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/lib'");
22517 }
22518 if(not -e $SystemRoot."/lib") {
22519 exitStatus("Access_Error", "can't access '".$SystemRoot."/lib'");
22520 }
22521 if(not -e $SystemRoot."/usr/include") {
22522 exitStatus("Access_Error", "can't access '".$SystemRoot."/usr/include'");
22523 }
22524 readSystemDescriptor("
22525 <name>
22526 $DumpSystem
22527 </name>
22528 <headers>
22529 $SystemRoot/usr/include
22530 </headers>
22531 <libs>
22532 $SystemRoot/usr/lib
22533 </libs>
22534 <search_libs>
22535 $SystemRoot/lib
22536 </search_libs>");
22537 }
22538 else {
22539 exitStatus("Error", "-sysroot <dirpath> option should be specified, usually it's \"/\"");
22540 }
22541 detect_default_paths("bin|gcc"); # to check symbols
22542 if($OStarget eq "windows")
22543 { # to run dumpbin.exe
22544 # and undname.exe
22545 check_win32_env();
22546 }
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022547 dumpSystem(getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022548 exit(0);
22549 }
22550 if($CmpSystems)
22551 { # --cmp-systems
22552 detect_default_paths("bin"); # to extract dumps
22553 loadModule("SysCheck");
Andrey Ponomarenko9927e332012-10-19 10:50:48 +040022554 cmpSystems($Descriptor{1}{"Path"}, $Descriptor{2}{"Path"}, getSysOpts());
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022555 exit(0);
22556 }
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022557 if($GenerateTemplate)
22558 {
22559 writeFile("VERSION.xml", $DescriptorTemplate."\n");
22560 printMsg("INFO", "XML-descriptor template ./VERSION.xml has been generated");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022561 exit(0);
22562 }
22563 if(not $TargetLibraryName) {
Andrey Ponomarenko570ece52012-11-30 16:36:44 +040022564 exitStatus("Error", "library name is not selected (-l option)");
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022565 }
22566 else
22567 { # validate library name
22568 if($TargetLibraryName=~/[\*\/\\]/) {
22569 exitStatus("Error", "\"\\\", \"\/\" and \"*\" symbols are not allowed in the library name");
22570 }
22571 }
22572 if(not $TargetLibraryFName) {
22573 $TargetLibraryFName = $TargetLibraryName;
22574 }
22575 if($CheckHeadersOnly_Opt and $CheckObjectsOnly_Opt) {
22576 exitStatus("Error", "you can't specify both -headers-only and -objects-only options at the same time");
22577 }
22578 if($SymbolsListPath)
22579 {
22580 if(not -f $SymbolsListPath) {
22581 exitStatus("Access_Error", "can't access file \'$SymbolsListPath\'");
22582 }
22583 foreach my $Interface (split(/\s*\n\s*/, readFile($SymbolsListPath))) {
22584 $SymbolsList{$Interface} = 1;
22585 }
22586 }
Andrey Ponomarenkofe00e7e2013-05-24 16:48:30 +040022587 if($SkipSymbolsListPath)
22588 {
22589 if(not -f $SkipSymbolsListPath) {
22590 exitStatus("Access_Error", "can't access file \'$SkipSymbolsListPath\'");
22591 }
22592 foreach my $Interface (split(/\s*\n\s*/, readFile($SkipSymbolsListPath))) {
22593 $SkipSymbolsList{$Interface} = 1;
22594 }
22595 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022596 if($SkipHeadersPath)
22597 {
22598 if(not -f $SkipHeadersPath) {
22599 exitStatus("Access_Error", "can't access file \'$SkipHeadersPath\'");
22600 }
22601 foreach my $Path (split(/\s*\n\s*/, readFile($SkipHeadersPath)))
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022602 { # register for both versions
22603 $SkipHeadersList{1}{$Path} = 1;
22604 $SkipHeadersList{2}{$Path} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022605 my ($CPath, $Type) = classifyPath($Path);
22606 $SkipHeaders{1}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022607 $SkipHeaders{2}{$Type}{$CPath} = 1;
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022608 }
22609 }
22610 if($ParamNamesPath)
22611 {
22612 if(not -f $ParamNamesPath) {
22613 exitStatus("Access_Error", "can't access file \'$ParamNamesPath\'");
22614 }
22615 foreach my $Line (split(/\n/, readFile($ParamNamesPath)))
22616 {
22617 if($Line=~s/\A(\w+)\;//)
22618 {
22619 my $Interface = $1;
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022620 if($Line=~/;(\d+);/)
22621 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022622 while($Line=~s/(\d+);(\w+)//) {
22623 $AddIntParams{$Interface}{$1}=$2;
22624 }
22625 }
Andrey Ponomarenko62ddcfa2012-05-23 13:13:15 +040022626 else
22627 {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022628 my $Num = 0;
22629 foreach my $Name (split(/;/, $Line)) {
22630 $AddIntParams{$Interface}{$Num++}=$Name;
22631 }
22632 }
22633 }
22634 }
22635 }
22636 if($AppPath)
22637 {
22638 if(not -f $AppPath) {
22639 exitStatus("Access_Error", "can't access file \'$AppPath\'");
22640 }
Andrey Ponomarenko16934472012-03-29 15:37:04 +040022641 foreach my $Interface (readSymbols_App($AppPath)) {
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022642 $SymbolsList_App{$Interface} = 1;
22643 }
22644 }
22645 if($DumpAPI)
22646 { # --dump-abi
22647 # make an API dump
22648 create_ABI_Dump();
22649 exit($COMPILE_ERRORS);
22650 }
22651 # default: compare APIs
22652 # -d1 <path>
22653 # -d2 <path>
Andrey Ponomarenko1bdef342012-03-19 17:23:47 +040022654 compareInit();
22655 if($JoinReport or $DoubleReport)
22656 {
22657 compareAPIs("Binary");
22658 compareAPIs("Source");
22659 }
22660 elsif($BinaryOnly) {
22661 compareAPIs("Binary");
22662 }
22663 elsif($SourceOnly) {
22664 compareAPIs("Source");
22665 }
Andrey Ponomarenkoab282102012-03-11 11:57:02 +040022666 exitReport();
22667}
22668
22669scenario();